首先準備一百粒米以上,粒粒完整無缺的米,裝於占卜八卦容器內,準備三個小碟子,依序做為上卦、下卦、動爻,並備有一香爐及八卦祖師像,所有占卜用品,必須清淨、且身心保持清淨專心一志的狀態,仲尼曰:「若一志,无聽之以耳而聽之以心,无聽之以心而聽之以氣。聽止於耳,心止於符。氣也者,虛而待物者也。唯道集虛。虛者,心齋也。」《莊子‧人間世》
一切就緒後,即可占卜,手搖米卦並口唸:「拜請八卦祖師伏羲、文王、周公、孔子四大聖賢、諸列神明、成卦童子、排卦童郎,今有善信○○○,因某某事由,誠心問卜,恭請八卦師伏羲、文王、周公、孔子四大聖賢、諸列神明、成卦童子、排卦童郎,顯示一卦指示吉凶分明,請賜上卦。」之後便將米卦盒放置正前方並開啟盒蓋,用手指抓出一小把米粒放置於上卦的碟子內。再曰:「上卦既成,請賜下卦。」再次用手指抓出一小把米粒放置於下卦的碟子內。曰:「下卦既成,請賜動爻。」同樣用手指抓出一小把米粒放置於動爻的碟子裡。最後曰:「動爻既成,叩謝八卦祖師伏羲、文王、周公、孔子四大聖賢、諸列神明、成卦童子、排卦童郎,賜卦指示,恭請諸列神明,復歸本位逍遙自在。」
占卜完成後,上下卦即以米數除以八,整除後之餘數即為卦數。餘數為1為乾卦、為2為兌卦、為3是離卦、為4是震卦、為5是巽卦、為6是坎卦、為7是艮卦、餘數為0為坤卦。
動爻之米數須用六除之,所得餘數即為動爻數,如餘1為初爻動、餘2為二爻動、餘3為三爻動、餘4為四爻動、餘5為五爻動、餘0為上爻動。
一 乾
二 兌
三 離
四 震
五 巽
六 坎
七 艮
八 坤
17 / 8 = 2 .......... 1
卦為乾
20 / 8 = 2 ...........4
卦為震
23 / 6 = 3 ...........5
五爻動
即得 本卦 為天雷无妄,變卦為水雷屯。
2015年12月27日 星期日
京房六十四卦分八宮
卦象歌:
乾為天,天風姤 ,天山遁,天地否,風地觀,山地剝,火地晉,火天大有
坎為水,水澤節,水雷屯,水火既濟,澤火革,雷火豐,地火明夷,地水師
艮為山,山火賁,山天大畜,山澤損,火澤睽,天澤履,風澤中孚,風山漸
震為雷,雷地豫,雷水解,雷風恒,地風升,水風井,澤風大過,澤雷隨
巽為風,風天小畜,風火家人,風雷益,天雷無妄,火雷噬嗑,山雷頤,山風蠱
離為火,火山旅,火風鼎,火水未濟,山水蒙,風水渙,天水訟,天火同人
坤為地,地雷復,地風升,地天泰,雷天大壯,澤天夬,水天需,水地比
兌為澤,澤水困,澤地萃,澤山咸,水山蹇,地山謙,雷山小過,雷澤歸妹
乾為天,天風姤 ,天山遁,天地否,風地觀,山地剝,火地晉,火天大有
坎為水,水澤節,水雷屯,水火既濟,澤火革,雷火豐,地火明夷,地水師
艮為山,山火賁,山天大畜,山澤損,火澤睽,天澤履,風澤中孚,風山漸
震為雷,雷地豫,雷水解,雷風恒,地風升,水風井,澤風大過,澤雷隨
巽為風,風天小畜,風火家人,風雷益,天雷無妄,火雷噬嗑,山雷頤,山風蠱
離為火,火山旅,火風鼎,火水未濟,山水蒙,風水渙,天水訟,天火同人
坤為地,地雷復,地風升,地天泰,雷天大壯,澤天夬,水天需,水地比
兌為澤,澤水困,澤地萃,澤山咸,水山蹇,地山謙,雷山小過,雷澤歸妹
文王六十四卦次序及掛變歌
文王六十四卦次序,就是《周易》的六十四卦排列次序,其上經三十卦,下經三十四卦。為了方便記憶,古人將其編成一首「卦序歌」,即:
乾坤屯蒙需訟師,比小畜兮履泰否。
同人大有謙豫隨,蠱臨觀兮噬嗑賁。
剝復無妄大畜頤,大過坎離三十備。
咸恒遁兮及大壯,晉與明夷家人睽。
蹇解損益夬姤萃,升困井革鼎震繼。
艮漸歸妹豐旅巽,兌渙節兮中孚至。
小過既濟兼未濟,是為下經三十四。
卦變歌又稱上下經變歌,對於研究《周易》掛辭、爻辭及掛象變化,有相當大的幫助,即:
訟自遁變泰歸妹,否從漸來隨三位。
首困噬嗑未濟兼,蠱三變賁井既濟。
噬嗑六五本益生,賁原於損既濟會。
無妄訟來大畜需,咸旅恒豐皆疑似。
震從觀更睽有三,離與中孚家人系。
蹇利西南小過來,解升二卦相為贅。
鼎由巽變漸渙旅,渙自漸來終於是。
卦歌的簡要解釋:
訟自遁變泰歸妹 訟卦是由遁卦的二爻與三爻轉動置換,就變成訟卦。泰卦是由歸妹卦的三爻與四爻移動置換就變成了泰卦。
否從漸來隨三位 否卦是由漸卦的三爻與四爻移動置換而成。隨卦的初爻與上爻置換移位也能變成否卦。或者將隨卦的初爻與三爻和四爻與上爻置換移位,就變成漸卦。
首困噬嗑未濟兼 困卦由噬嗑卦的初爻與二爻和五爻與上爻置換移位,就變成困卦。未濟卦的五爻與上爻移位置換也能變成困卦。
蠱三變賁井既濟 蠱卦的初爻與二爻置換移位,就變成了賁卦,蠱卦的五爻與上爻置換移位,就變成了井卦,蠱卦的初爻與二爻,和五爻與上爻均置換移位就變成了既濟卦。
噬嗑六五本益生 噬嗑卦的六五爻(即第五爻陰爻)本來就是由益卦的四爻與五爻置換移位而生成的。
賁原於損既濟會 賁卦是由損卦的二爻與三爻置換移位而變成的。既濟卦的五爻與上爻置換移位也能變成賁卦。
無妄訟來大畜需 無妄卦是由訟卦的初爻與二爻置換移位而變成。大畜卦由需卦的五爻與上爻置換置換移位而成。
咸旅恒豐皆疑似 咸卦由旅卦的五爻與上爻位置而成。恒卦由豐卦的初爻與二爻移位置換而成。
震從觀更睽有三 晉卦是從觀卦的四爻與五爻移位置換而成。若將睽卦的初爻二爻與三爻變為陰爻就是晉卦了。
離與中孚家人系 離卦由家人卦的四爻與五爻移位置換而成離卦。中孚卦為大離象,也是由家人卦的二爻與三爻移位置換而成中孚卦。
蹇利西南小過來 蹇卦由小過卦的四爻與五爻移位置換而成。小過卦為大坎象,可按坎卦斷事。蹇難也,坎重險也,其義可通。
解升二卦相為贅 解卦由升卦的三爻與四爻移位置換而成,也可以由解卦的三爻與四爻移位置換而成。
鼎由巽變漸渙旅 鼎卦由巽卦的四爻與五爻移位置換而來。漸卦由渙卦的二爻與三爻移位置換而來。旅卦由漸卦的四爻與五爻移位置換而來,或者由渙卦的二爻與三爻及四爻與五爻的移位置換而為旅卦。
渙自漸來終於是 渙卦由漸卦的二爻與三爻移位置換而成。
乾坤屯蒙需訟師,比小畜兮履泰否。
同人大有謙豫隨,蠱臨觀兮噬嗑賁。
剝復無妄大畜頤,大過坎離三十備。
咸恒遁兮及大壯,晉與明夷家人睽。
蹇解損益夬姤萃,升困井革鼎震繼。
艮漸歸妹豐旅巽,兌渙節兮中孚至。
小過既濟兼未濟,是為下經三十四。
卦變歌又稱上下經變歌,對於研究《周易》掛辭、爻辭及掛象變化,有相當大的幫助,即:
訟自遁變泰歸妹,否從漸來隨三位。
首困噬嗑未濟兼,蠱三變賁井既濟。
噬嗑六五本益生,賁原於損既濟會。
無妄訟來大畜需,咸旅恒豐皆疑似。
震從觀更睽有三,離與中孚家人系。
蹇利西南小過來,解升二卦相為贅。
鼎由巽變漸渙旅,渙自漸來終於是。
卦歌的簡要解釋:
訟自遁變泰歸妹 訟卦是由遁卦的二爻與三爻轉動置換,就變成訟卦。泰卦是由歸妹卦的三爻與四爻移動置換就變成了泰卦。
否從漸來隨三位 否卦是由漸卦的三爻與四爻移動置換而成。隨卦的初爻與上爻置換移位也能變成否卦。或者將隨卦的初爻與三爻和四爻與上爻置換移位,就變成漸卦。
首困噬嗑未濟兼 困卦由噬嗑卦的初爻與二爻和五爻與上爻置換移位,就變成困卦。未濟卦的五爻與上爻移位置換也能變成困卦。
蠱三變賁井既濟 蠱卦的初爻與二爻置換移位,就變成了賁卦,蠱卦的五爻與上爻置換移位,就變成了井卦,蠱卦的初爻與二爻,和五爻與上爻均置換移位就變成了既濟卦。
噬嗑六五本益生 噬嗑卦的六五爻(即第五爻陰爻)本來就是由益卦的四爻與五爻置換移位而生成的。
賁原於損既濟會 賁卦是由損卦的二爻與三爻置換移位而變成的。既濟卦的五爻與上爻置換移位也能變成賁卦。
無妄訟來大畜需 無妄卦是由訟卦的初爻與二爻置換移位而變成。大畜卦由需卦的五爻與上爻置換置換移位而成。
咸旅恒豐皆疑似 咸卦由旅卦的五爻與上爻位置而成。恒卦由豐卦的初爻與二爻移位置換而成。
震從觀更睽有三 晉卦是從觀卦的四爻與五爻移位置換而成。若將睽卦的初爻二爻與三爻變為陰爻就是晉卦了。
離與中孚家人系 離卦由家人卦的四爻與五爻移位置換而成離卦。中孚卦為大離象,也是由家人卦的二爻與三爻移位置換而成中孚卦。
蹇利西南小過來 蹇卦由小過卦的四爻與五爻移位置換而成。小過卦為大坎象,可按坎卦斷事。蹇難也,坎重險也,其義可通。
解升二卦相為贅 解卦由升卦的三爻與四爻移位置換而成,也可以由解卦的三爻與四爻移位置換而成。
鼎由巽變漸渙旅 鼎卦由巽卦的四爻與五爻移位置換而來。漸卦由渙卦的二爻與三爻移位置換而來。旅卦由漸卦的四爻與五爻移位置換而來,或者由渙卦的二爻與三爻及四爻與五爻的移位置換而為旅卦。
渙自漸來終於是 渙卦由漸卦的二爻與三爻移位置換而成。
2015年12月23日 星期三
執行緒類別ThreadStart的使用
using System ;
using System.Threading ;
namespace Test_Thread
{
public class MyThread
{
public void TestThread ( )
{
for (int i = 0 ; i < 3 ; i++)
{
Console.WriteLine ("執行緒 : {0} " , i ) ;
}
}
}
public class Test
{
public static void Main ( )
{
Console.WriteLine ("開始啟動執行緒:") ;
MyThread myThread1 = new MyThread ( ) ;
MyThread myThread2 = new MyThread ( ) ;
ThreadStart ts1 = new ThreadStart (myThread1.TestThread) ;
ThreadStart ts2 = new ThreadStart (myThread2.TestThread) ;
Thread a = new Thread ( ts1) ;
Thread b = new Thread ( ts2) ;
a.Start ( ) ;
b.Start ( ) ;
}
}
}
範例中首先使用"MyThread myThread1 = new MyThread ( ) ;"語法建立一個MyThread的實例
myThread1,然後使用"ThreadStart ts1 = new ThreadStart (myThread1.TestThread) ;"語法建立一個ThreadStart委派的實例 ts1,最後使用"Thread a = new Thread ( ts1) ;"語法將ts1傳給Thread類別的建構子,並建立了一個Thread類別的實例 a。
using System.Threading ;
namespace Test_Thread
{
public class MyThread
{
public void TestThread ( )
{
for (int i = 0 ; i < 3 ; i++)
{
Console.WriteLine ("執行緒 : {0} " , i ) ;
}
}
}
public class Test
{
public static void Main ( )
{
Console.WriteLine ("開始啟動執行緒:") ;
MyThread myThread1 = new MyThread ( ) ;
MyThread myThread2 = new MyThread ( ) ;
ThreadStart ts1 = new ThreadStart (myThread1.TestThread) ;
ThreadStart ts2 = new ThreadStart (myThread2.TestThread) ;
Thread a = new Thread ( ts1) ;
Thread b = new Thread ( ts2) ;
a.Start ( ) ;
b.Start ( ) ;
}
}
}
範例中首先使用"MyThread myThread1 = new MyThread ( ) ;"語法建立一個MyThread的實例
myThread1,然後使用"ThreadStart ts1 = new ThreadStart (myThread1.TestThread) ;"語法建立一個ThreadStart委派的實例 ts1,最後使用"Thread a = new Thread ( ts1) ;"語法將ts1傳給Thread類別的建構子,並建立了一個Thread類別的實例 a。
2015年12月22日 星期二
處理序與執行緒的關係
- 一個執行緒只屬於一個處理序,而一個處理序可以有多個執行緒,或至少有一個執行緒。
- 資源分配給處理序,在同一個處理序的所有執行緒共用該處理序的所有資源。
- 處理器分給執行緒,即真正在處理器上運行的是執行緒。
- 執行緒在執行過程中,需要協作同步。不同的執行緒間可利用訊息通訊的辦法實作同步。
1.啟動一個處理序
Public static void Main( )
{
Process p = new Process ( ) ;
p.StartInfo.FileName = "notepad.exe" ; //設置需要啟動處理序的名稱
p.StartInfo.WindowsStyle = ProcessWindowsStyle.Maximized; //在設定啟動處理序時,新視窗的顯示樣式
p.Start ( ) ;//開始啟動處理序
}
2.關閉一個處理序
Public static void Main( )
{
Process [ ] p = Process.GetProcessesByName ("notepad") ;
if (p.Length > 0 )
{
if ( !p [0].HasExited) //用來確定處理序是否關閉,假如已經關閉則回傳true屬性值,否則為false
{
if ( p[0].Responding) //發送一個請求介面,假如立即有回應則回傳一個true
{
p[0].CloseMainWindow ( ) ; //叫用 CloseMainWindows方法關閉應用程式
}
else
{
p[0].Kill ( ) ;//若沒有回應則叫用Kill方法強制處理序關閉。
}
}
}
}
3.獲得目前電腦系統內所有已啟動的處理序
Public static void Main ( )
{
Process [ ] processOnComputer = Process.GetProcesses ( ) ;
foreach (Process p in processOnComputer)
{
Console.WriteLine (p.ToString ( ) );
}
}
4.簡單的執行緒例子
using System ;
using System.Threading ;
namespace Test_Thread
{
public class Test
{
public static void ThreadA ( )
{
for (int i = 0 ; i < 3 ; i++ )
{
Console.WriteLine ( "執行緒 A : {0} ", i ) ;
}
}
public static void ThreadB ( )
{
for (int i = 0 ; i < 3 ; i++ )
{
Console.WriteLine ("執行緒B : {0} ", i ) ;
}
}
public static void Main ( )
{
Console.WriteLine ("開始啟動執行緒 :") ;
Thread a = new Thread (new ThreadStart (ThreadA)) ;
Thread b = new Thread (new ThreadStart (ThreadB)) ;
//叫用Start ( )可以啟動執行緒,但是叫用Start ( )之後,新執行緒並不處於Running狀態,而是處於Unstarted狀態。作業系統的執行緒調度器選擇了要運行的執行緒之後,執行緒才會改變為Running狀態。
a.Start ( ) ;
b.Start ( ) ;
}
}
}
2015年12月19日 星期六
靜態物件導向與動態物件導向的差別
拜讀松本弘二先生(Ruby的創始人)的大作,其中一個說到什麼是靜態物件導向與動態物件導向的差別。
所謂靜態物件導向程式語言(Java,C#)必須宣告型別給物件使用,動態物件導向程式語言(Ruby)不必宣告型別給物件(電腦在編譯程式會自動判斷並給予型別)。
宣告型別在於不必執行程式便可以閱讀程式了解程式執行的結果,但程式內容較複雜。
不宣告型別能使程式簡潔、乾淨、俐落,但一定要執行程式才能知道結果。
所謂靜態物件導向程式語言(Java,C#)必須宣告型別給物件使用,動態物件導向程式語言(Ruby)不必宣告型別給物件(電腦在編譯程式會自動判斷並給予型別)。
宣告型別在於不必執行程式便可以閱讀程式了解程式執行的結果,但程式內容較複雜。
不宣告型別能使程式簡潔、乾淨、俐落,但一定要執行程式才能知道結果。
使用XmlSerializer進行序列化
using System ;
using System.IO ;
using System.Xml.Serialization ;
namespace Xml_serial
{
public class Student
{
private string name ;
public string Name //為Name設定屬性
{
get
{
return name ;
}
set
{
name = value ;
}
}
public string Sex ;
public int Age = 30 ;
public Course [ ] Courses ;
public Student ( ) //無參數的建構子
{
}
public Student (string Name) //帶一個參數的建構子
{
name = Name ;
Sex = " Male " ;
}
}
public class Course //無參數的建構子
{
public string Name ;
[XmlIgnore]
public string Description ;//使用[XmlIgnore]表示不生成XML
public Course ( )
{
}
public Course (string name, string description) //帶兩個參數的建構子
{
Name = name ;
Description = description ;
}
}
public class Test
{
public void XMLSerialize ( ) //序列化成XML
{
Student stu = new Student ("小李") ;
stu.Course = new Course [2] ;
stu.Course [0] = new Course ("國文", "語言課") ;
stu.Course [1] = new Course ("英文", "語言課") ;
XmlSerializer x = new XmlSerializer (typeof (Student) ) ;
Stream stream = new FileStream ("c:\\student.xml", FileMode.Create,
FileAccess.Write, FileShare.Read) ;
x.Serialize (stream, stu) ; //執行序列化
stream.Close ( ) ;
}
public void XMLDeserialize ( ) //反序列化 (還原)
{
XmlSerializer x =new XmlSerializer(typeof (Student) ) ;
Stream stream = new FileStream ("c:\\student.xml", FileMode.Open,
FileAccess.Read, FileShare.Read) ;
Student stu = x.Deserialize (stream) as Student ;//執行反序列化
Console.WriltrLine (stu.Age.ToString ( ) ) ;
Console.WriteLine (stu.Courses [0] .Name) ;
Console.WriteLine (stu.Courses [0] .Description) ;
Console.WriteLine (stu.Coruses [1] .Name) ;
Console.WriteLine (stu.Coruses [1] .Description) ;
stream.Close ( ) ;
}
public static void Main ( )
{
Test test = new Test ( ) ;
test.XMLSerialize ( ) ;
test.XMLDeserialize ( ) ;
}
}
}
因為Description變數使用XmlIgnore屬性,所以它的值是null,創見的XML文件也就沒有該節點。
using System.IO ;
using System.Xml.Serialization ;
namespace Xml_serial
{
public class Student
{
private string name ;
public string Name //為Name設定屬性
{
get
{
return name ;
}
set
{
name = value ;
}
}
public string Sex ;
public int Age = 30 ;
public Course [ ] Courses ;
public Student ( ) //無參數的建構子
{
}
public Student (string Name) //帶一個參數的建構子
{
name = Name ;
Sex = " Male " ;
}
}
public class Course //無參數的建構子
{
public string Name ;
[XmlIgnore]
public string Description ;//使用[XmlIgnore]表示不生成XML
public Course ( )
{
}
public Course (string name, string description) //帶兩個參數的建構子
{
Name = name ;
Description = description ;
}
}
public class Test
{
public void XMLSerialize ( ) //序列化成XML
{
Student stu = new Student ("小李") ;
stu.Course = new Course [2] ;
stu.Course [0] = new Course ("國文", "語言課") ;
stu.Course [1] = new Course ("英文", "語言課") ;
XmlSerializer x = new XmlSerializer (typeof (Student) ) ;
Stream stream = new FileStream ("c:\\student.xml", FileMode.Create,
FileAccess.Write, FileShare.Read) ;
x.Serialize (stream, stu) ; //執行序列化
stream.Close ( ) ;
}
public void XMLDeserialize ( ) //反序列化 (還原)
{
XmlSerializer x =new XmlSerializer(typeof (Student) ) ;
Stream stream = new FileStream ("c:\\student.xml", FileMode.Open,
FileAccess.Read, FileShare.Read) ;
Student stu = x.Deserialize (stream) as Student ;//執行反序列化
Console.WriltrLine (stu.Age.ToString ( ) ) ;
Console.WriteLine (stu.Courses [0] .Name) ;
Console.WriteLine (stu.Courses [0] .Description) ;
Console.WriteLine (stu.Coruses [1] .Name) ;
Console.WriteLine (stu.Coruses [1] .Description) ;
stream.Close ( ) ;
}
public static void Main ( )
{
Test test = new Test ( ) ;
test.XMLSerialize ( ) ;
test.XMLDeserialize ( ) ;
}
}
}
因為Description變數使用XmlIgnore屬性,所以它的值是null,創見的XML文件也就沒有該節點。
2015年12月18日 星期五
序列化與反序列化
序列化是指將物件實例的狀態儲存到儲存媒體上。此過程先將物件的公用欄位和私有欄位以及類別的名稱轉換為位元組流(Bitstream),然後再把位元組流寫入資料流程。在隨後對對象進行反序列化時,將建立出與原對象完全相同的副本。這個過程成為序列化與反序列化,又稱串列化與反串列化。
序列化與反序列化主要目的在於減少網路流量,減輕伺服器的資料處理壓力,進而節省了登錄時間。
為了讓物件支援.NET序列化服務,必須為每一個關聯的類別加上[Serializable]特性。如果認為給定的類別成員資料不能參與序列化的配置,則可以在成員資料之前加上[NonSerialized]的關鍵字,如下:
[Serializable]
public calss Login
{
private string S_username;
private string s_password;
[NonSerialized]
private string s_userid;
public string UserName
{
get
{
return s_username;
}
set
{
this.s_username = value ;
}
}
public string Password
{
get
{
return s_password ;
}
set
{
this.s_password = value ;
}
}
public string Userid
{
get
{
return s_userid ;
}
set
{
this.s_serid = value ;
}
}
}
public class Test
{
//序列化使用 BinaryFormatte
public void BinaryFormatterSerialize( )
{
Login login = new Login ( ) ;
login.UserName = "admin" ;
login.Password = "123456" ;
login.UserID = "s1" ;
FileStream fileStream = new FileStream ("c:\\User.dat" , FileMode.Create) ;
BinaryFormatter b = new BinaryFormatter ( ) ;
//將一個物件圖移位元組的順序持久化到一個指定資料流
b.Serialize(fileStream, login) ;
fileStream.Close( ) ;
}
// 反序列化
public void BinaryFormatterDeSerialize( )
{
Login login = new Login( ) ;
FileStream fileStream = new FileStream ("c:\\User.dat" , FileMode.Open,
FileAccess.Read, FileShare.Read ) ;
BinaryFormatter b = new BinaryFormatter ( ) ;
//將一個持久化的位元組順序轉化為一個物件圖
login = b.Deserialize (fileStream) as Login ;
Console.WriteLine (login.UserName) ;
Console.WriteLine (login.Password) ;
Console.WriteLine (login.UserID) ;
fileStream.Close ( ) ;
}
public static void Main ( )
{
Test test = new Test ( ) ;
test.BinaryFormatterSerialize ( ) ;
tes.DeBinaryFormatterSerialize ( ) ;
}
}
}
上面的程式碼 Login類別被標記為[Serializable],而成員變數s_userid被標記為 [NonSerialized],因此s_userid不參與序列化。
C#提供了三種序列化的方式:
1.使用BinaryFormatter進行序列化
using System.Runtime.Serialization.Formatters.Binary ;
2.使用SoapFormatter進行序列化
using System.Runtime.Serialization.Formatters.Soap ;
3.使用XmlSerial進行序列化
using System.Xml.Serialization ;
三者差異在於BinaryFormatter可以完整保存欄位資料之外,對每一個類型的完整修飾名詞和定義組件的完整名稱都可以完整保留。而SoapFormatter與XmlSerial並不記錄完整的修飾名詞或起源組件,僅僅保留公共欄位或公共屬性,因為Xml具有開放性的原則,就不要保有完整的類型。
序列化與反序列化主要目的在於減少網路流量,減輕伺服器的資料處理壓力,進而節省了登錄時間。
為了讓物件支援.NET序列化服務,必須為每一個關聯的類別加上[Serializable]特性。如果認為給定的類別成員資料不能參與序列化的配置,則可以在成員資料之前加上[NonSerialized]的關鍵字,如下:
[Serializable]
public calss Login
{
private string S_username;
private string s_password;
[NonSerialized]
private string s_userid;
public string UserName
{
get
{
return s_username;
}
set
{
this.s_username = value ;
}
}
public string Password
{
get
{
return s_password ;
}
set
{
this.s_password = value ;
}
}
public string Userid
{
get
{
return s_userid ;
}
set
{
this.s_serid = value ;
}
}
}
public class Test
{
//序列化使用 BinaryFormatte
public void BinaryFormatterSerialize( )
{
Login login = new Login ( ) ;
login.UserName = "admin" ;
login.Password = "123456" ;
login.UserID = "s1" ;
FileStream fileStream = new FileStream ("c:\\User.dat" , FileMode.Create) ;
BinaryFormatter b = new BinaryFormatter ( ) ;
//將一個物件圖移位元組的順序持久化到一個指定資料流
b.Serialize(fileStream, login) ;
fileStream.Close( ) ;
}
// 反序列化
public void BinaryFormatterDeSerialize( )
{
Login login = new Login( ) ;
FileStream fileStream = new FileStream ("c:\\User.dat" , FileMode.Open,
FileAccess.Read, FileShare.Read ) ;
BinaryFormatter b = new BinaryFormatter ( ) ;
//將一個持久化的位元組順序轉化為一個物件圖
login = b.Deserialize (fileStream) as Login ;
Console.WriteLine (login.UserName) ;
Console.WriteLine (login.Password) ;
Console.WriteLine (login.UserID) ;
fileStream.Close ( ) ;
}
public static void Main ( )
{
Test test = new Test ( ) ;
test.BinaryFormatterSerialize ( ) ;
tes.DeBinaryFormatterSerialize ( ) ;
}
}
}
上面的程式碼 Login類別被標記為[Serializable],而成員變數s_userid被標記為 [NonSerialized],因此s_userid不參與序列化。
C#提供了三種序列化的方式:
1.使用BinaryFormatter進行序列化
using System.Runtime.Serialization.Formatters.Binary ;
2.使用SoapFormatter進行序列化
using System.Runtime.Serialization.Formatters.Soap ;
3.使用XmlSerial進行序列化
using System.Xml.Serialization ;
三者差異在於BinaryFormatter可以完整保存欄位資料之外,對每一個類型的完整修飾名詞和定義組件的完整名稱都可以完整保留。而SoapFormatter與XmlSerial並不記錄完整的修飾名詞或起源組件,僅僅保留公共欄位或公共屬性,因為Xml具有開放性的原則,就不要保有完整的類型。
2015年12月17日 星期四
類別庫項目的參考
在visual studio 2015中新增類別,該類別封裝所有程式的商業邏輯,例如:
using System;
namespace Test_Class
{
public enum Lange
{
English, Chinese
}
public class ManagerHello
{
private void EnglishGreeting(string name)
{
Console.WriteLine("Hello, " + name) ;
}
private void ChineseGreeting(string name)
{
Console.WriteLine("你好 " + name) ;
}
public void GreetHello(string name, Language lang)
{
switch (lang)
{
case Language.English :
EnglishGreeting (name);
break ;
case Language.Chinese :
ChineseGreeting (name) ;
break ;
}
}
}
}
在編譯這個項目之後,可以在 bin/Debug資料夾裡產生一個名為Test_Class的dll檔,就是所謂的組件,或是說在.NET 項目編譯之後產生的*.exe 或 *.dll 的檔案。
要叫用 Test_Class 組件可以在現行或新增應用程式專案時參考這個組件。例如我們新增一個主控台應用程式並點選標籤 References 加入參考,使用瀏覽找出所要參考的組件並按確定,在References底下就會新增所要參考的組件名稱。再來就是引用這個組件例如:
using System;
using Test_Class;
namespace C_ref
{
public class Program
{
public static void Main ( )
{
ManagerHello hi = new ManagerHello ( ) ;
hi.GreetHello ("John ", Language.English ) ;
hi.GreetHello ("張三 ", Language.Chinese ) ;
}
}
}
using System;
namespace Test_Class
{
public enum Lange
{
English, Chinese
}
public class ManagerHello
{
private void EnglishGreeting(string name)
{
Console.WriteLine("Hello, " + name) ;
}
private void ChineseGreeting(string name)
{
Console.WriteLine("你好 " + name) ;
}
public void GreetHello(string name, Language lang)
{
switch (lang)
{
case Language.English :
EnglishGreeting (name);
break ;
case Language.Chinese :
ChineseGreeting (name) ;
break ;
}
}
}
}
在編譯這個項目之後,可以在 bin/Debug資料夾裡產生一個名為Test_Class的dll檔,就是所謂的組件,或是說在.NET 項目編譯之後產生的*.exe 或 *.dll 的檔案。
要叫用 Test_Class 組件可以在現行或新增應用程式專案時參考這個組件。例如我們新增一個主控台應用程式並點選標籤 References 加入參考,使用瀏覽找出所要參考的組件並按確定,在References底下就會新增所要參考的組件名稱。再來就是引用這個組件例如:
using System;
using Test_Class;
namespace C_ref
{
public class Program
{
public static void Main ( )
{
ManagerHello hi = new ManagerHello ( ) ;
hi.GreetHello ("John ", Language.English ) ;
hi.GreetHello ("張三 ", Language.Chinese ) ;
}
}
}
閒話家常
接觸 Access資料庫也有一段時間,雖然中間有停頓過,但憑著當初學習的阿甘精神,基礎有打穩,現在再來接觸它倍感親切,也才發現它的好。
自從學了C#語言之後,物件導向的觀念也建立了,但就是無下手處,想來想去,所謂下手處要從自己所熟悉的軟體著手才是。Access 親和與直覺的操作讓人迷戀不已,但卻也寵壞了不少軟體使用者,面對必須從零開始的架構,倒是覺得有些不適應,也會想說,微軟都幫你建好這樣的架構了,自己還要另起地基不是很浪費時間嗎。
Access 雖然好用,但畢竟只是微軟的一個策略而已,一種吸引人的策略,讓你似懂非懂的感覺。也就是說高深的技術我來,組合軟體的功能把戲給你就好。讓人有一種,這樣複雜的架構你可以懂,但你沒那麼多時間來做,我來幫你完成的感覺。我不能說不好,坦白講其立意與出發點是好的。事實上,好的另一面有不好。都有一個對立面,這是不爭的事實。我所謂不好,不是指軟體不好用,功能不夠等,而是人的依賴程度會被放大。處理家庭事務,小公司沒佘問題,若面對大公司的需求,卻捉襟見肘了。
當然 Access可以幫助完成許多事情,這是不爭的事實。但嚴格說起來只是一個入門級的軟體而已,要想朝更進階的程度邁進,就得找回當初的阿甘精神。用 Access為輔C#為主的主客關係看待,讓新觀念不斷的建立與既有的基礎相結合,為軟體學習之道不斷的鋪路。
自從學了C#語言之後,物件導向的觀念也建立了,但就是無下手處,想來想去,所謂下手處要從自己所熟悉的軟體著手才是。Access 親和與直覺的操作讓人迷戀不已,但卻也寵壞了不少軟體使用者,面對必須從零開始的架構,倒是覺得有些不適應,也會想說,微軟都幫你建好這樣的架構了,自己還要另起地基不是很浪費時間嗎。
Access 雖然好用,但畢竟只是微軟的一個策略而已,一種吸引人的策略,讓你似懂非懂的感覺。也就是說高深的技術我來,組合軟體的功能把戲給你就好。讓人有一種,這樣複雜的架構你可以懂,但你沒那麼多時間來做,我來幫你完成的感覺。我不能說不好,坦白講其立意與出發點是好的。事實上,好的另一面有不好。都有一個對立面,這是不爭的事實。我所謂不好,不是指軟體不好用,功能不夠等,而是人的依賴程度會被放大。處理家庭事務,小公司沒佘問題,若面對大公司的需求,卻捉襟見肘了。
當然 Access可以幫助完成許多事情,這是不爭的事實。但嚴格說起來只是一個入門級的軟體而已,要想朝更進階的程度邁進,就得找回當初的阿甘精神。用 Access為輔C#為主的主客關係看待,讓新觀念不斷的建立與既有的基礎相結合,為軟體學習之道不斷的鋪路。
2015年12月16日 星期三
簡介 Kanban 與 Scrum
Kanban 的大意就是將資訊以視覺化的方式呈現出來,從 Do ,Doing 到 Done
Do 類似於計畫的規畫與設計。
Doing 表示現在正在進行的計畫或正在執行的工作項目。
Done 表示已經執行完畢或是已經做過的工作項目。
對於 Kanban 的引用主要是使專案的推動視覺化、透明化與整體化,清楚的了解專案進度的推動與預計時程的掌握,可以清楚知道障礙的發生以及應付問題所應採取的對策。不斷的修正與調整計畫的進行,讓計畫能夠順利執行下去。
Scrum 是橄欖球隊的用語,是爭球的意思。將Scrum的觀念應用在專案的推動上,可以使專案的進度加快速度。Scrum用於討論如:
Scrum不同於瀑布(WaterFall)示的結構流程,Scrum是以反覆回饋的方式在推動,結果可以很快的知道與呈現。
Do 類似於計畫的規畫與設計。
Doing 表示現在正在進行的計畫或正在執行的工作項目。
Done 表示已經執行完畢或是已經做過的工作項目。
對於 Kanban 的引用主要是使專案的推動視覺化、透明化與整體化,清楚的了解專案進度的推動與預計時程的掌握,可以清楚知道障礙的發生以及應付問題所應採取的對策。不斷的修正與調整計畫的進行,讓計畫能夠順利執行下去。
Scrum 是橄欖球隊的用語,是爭球的意思。將Scrum的觀念應用在專案的推動上,可以使專案的進度加快速度。Scrum用於討論如:
- 昨天你完成了那些工作。
- 今天你打算要做什麼。
- 完成你的目標,是否存在什麼障礙。
Scrum不同於瀑布(WaterFall)示的結構流程,Scrum是以反覆回饋的方式在推動,結果可以很快的知道與呈現。
委派與匿名方法
匿名方法(Anonymous Method)允許一個與委派關聯的程式碼被寫入在使用委派的地方,這樣的好處是對於委派的實例很直接。也就是直接將方法的程式碼區塊做為參數傳給委派而不必叫用方法。如下:
//定義一個委派
delegate void Del(int x) ;
//委派叫用匿名方法(含有void 的方法)
Del d = delegate (int y)
{
//委派所叫用方法的程式碼
return ;
} ;
//委派叫用匿名方法(不含有void 的方法 指定回傳值 (int 型別) )
delegate int MyDelegate ( )
MyDelegate d = delegate
{
‧‧‧
return 123 ;
} ;
又如執行緒類別建立一個執行緒並且包含該執行緒執行的程式碼,如下:
void StartThread ( )
{
Thread t = new Thread (delegate ( )
{
Console.Write ("Hello, ") ;
Console.WriteLine ("World ! ") ;
} ) ;
t.Start ( ) ;
}
//定義一個委派
delegate void Del(int x) ;
//委派叫用匿名方法(含有void 的方法)
Del d = delegate (int y)
{
//委派所叫用方法的程式碼
return ;
} ;
//委派叫用匿名方法(不含有void 的方法 指定回傳值 (int 型別) )
delegate int MyDelegate ( )
MyDelegate d = delegate
{
‧‧‧
return 123 ;
} ;
又如執行緒類別建立一個執行緒並且包含該執行緒執行的程式碼,如下:
void StartThread ( )
{
Thread t = new Thread (delegate ( )
{
Console.Write ("Hello, ") ;
Console.WriteLine ("World ! ") ;
} ) ;
t.Start ( ) ;
}
委派的多點傳送(多點傳送委派)
多點傳送委派是指參考多個委派方法。當叫用委派時,它會叫用每個方法。要注意的是委派必須是同型別,且回傳型別必須是void。也就是說不能有輸出參數,但可以帶有參考參數。
在現實世界中如同你一個人幫多人代繳學費的意思是一樣的。
範例如下:
using System;
namespace Test_Delegate
{
//宣告委派
delegate void TestDelegate (double value) ;
//宣告類別
public class MyDelegate
{
//方法一
public static void F (double value)
{
double result = vaule * 2 ;
Console.WrileLine ("F-value: { 0 } result { 1 } ", value, result) ;
}
//方法二
public static void F2 (double value)
{
double result = value * 3 ;
Console.WrilteLine ("F2-value: { 0 } result { 1 } ", value, result) ;
}
//方法三
public static void F3 (double value)
{
double result = value *value ;
Consle.WriteLine ("F3-value: { 0 } result { 1 } ", value, result) ;
}
}
//宣告類別
public class Test
{
public static void Main ( )
{
//設定傳入委派的參數
double x_value=1.732 ;
//實作一個委派物件
TestDelegate test = new TestDelegate (MyDelegate.F) ;
//傳入第二個委派
test += new TestDelegate (MyDelegate.F2) ;
//傳入第三個委派
test += new TestDelegate (MyDelegate F3) ;
//傳入參數
test (x_value) ;
Console.WriteLine (" 取消F2後的結果 ") ;
//取消F2的委派
test -= new TestDelegate (MyDelegate F2) ;
test (x_value) ;
}
}
}
在現實世界中如同你一個人幫多人代繳學費的意思是一樣的。
範例如下:
using System;
namespace Test_Delegate
{
//宣告委派
delegate void TestDelegate (double value) ;
//宣告類別
public class MyDelegate
{
//方法一
public static void F (double value)
{
double result = vaule * 2 ;
Console.WrileLine ("F-value: { 0 } result { 1 } ", value, result) ;
}
//方法二
public static void F2 (double value)
{
double result = value * 3 ;
Console.WrilteLine ("F2-value: { 0 } result { 1 } ", value, result) ;
}
//方法三
public static void F3 (double value)
{
double result = value *value ;
Consle.WriteLine ("F3-value: { 0 } result { 1 } ", value, result) ;
}
}
//宣告類別
public class Test
{
public static void Main ( )
{
//設定傳入委派的參數
double x_value=1.732 ;
//實作一個委派物件
TestDelegate test = new TestDelegate (MyDelegate.F) ;
//傳入第二個委派
test += new TestDelegate (MyDelegate.F2) ;
//傳入第三個委派
test += new TestDelegate (MyDelegate F3) ;
//傳入參數
test (x_value) ;
Console.WriteLine (" 取消F2後的結果 ") ;
//取消F2的委派
test -= new TestDelegate (MyDelegate F2) ;
test (x_value) ;
}
}
}
宣告事件三
事件也可以在介面中宣告,如下:
using System;
namespaace Test_Event
{
//宣告一個委派
public delegate void TestDelegate( ) ;
//宣告一個介面
public interface ITestInterface
{
//宣告一個TestEvent事件
event TestDeleage TestEvent ;
//宣告一個方法(操作)
void Test( ) ;
}
public class MyClass : ITestInterface
{
//實作事件
public event TestDeleage TestEvent ;
//實作方法
public void Test( )
{
if (TestEvent != null )
{
TestEvent ( ) ;
}
}
}
//宣告一個類別
public class Test
{
private static void F( )
{
Console.WriteLine ("這是事件測試 !! ") ;
}
public static void Main( )
{
//產生 名為 i 的物件
ITestInterface i = new MyClass ( ) ;
//叫用事件
i.TestEvent += new TestDelegate ( F ) ;
//執行方法
i.Test ( ) ;
}
}
}
using System;
namespaace Test_Event
{
//宣告一個委派
public delegate void TestDelegate( ) ;
//宣告一個介面
public interface ITestInterface
{
//宣告一個TestEvent事件
event TestDeleage TestEvent ;
//宣告一個方法(操作)
void Test( ) ;
}
public class MyClass : ITestInterface
{
//實作事件
public event TestDeleage TestEvent ;
//實作方法
public void Test( )
{
if (TestEvent != null )
{
TestEvent ( ) ;
}
}
}
//宣告一個類別
public class Test
{
private static void F( )
{
Console.WriteLine ("這是事件測試 !! ") ;
}
public static void Main( )
{
//產生 名為 i 的物件
ITestInterface i = new MyClass ( ) ;
//叫用事件
i.TestEvent += new TestDelegate ( F ) ;
//執行方法
i.Test ( ) ;
}
}
}
2015年12月15日 星期二
Asp.net 之 Web Form VS MVC
對於Web Form 與 MVC 兩者究竟孰優孰劣,至今尚未能見分曉,但可以確定的是,微軟對於Web Form 會一直支持下去,因為Web Form 所提供的控制項是無可取代的,能夠快速的建立個專案網頁是Web Form 的強項。
但是,對於後起之秀MVC則有急起直追的趨勢,MVC是model,view,control 三者的簡稱。微軟在樣式與邏輯分離的控制層面上,似乎落後競爭對手許多,例如:Java ,Php 等知名軟體都在MVC上著墨一段時間。MVC 對於使用ASP.NET的人來說,是一種新的概念,故在設計與規劃上面,比起Web Form必須花費較多的時間在規畫上面,不過一旦完成規畫設計,對於後續的維護與擴充,則是Web Form所望塵莫及的。
然而,對於一個網頁學習者來說,究竟是先學 Web Form好呢?或者是直接學習MVC的架構。個人認為,視將來所要面對的工作環境做一個判斷準則。如果只是一般的小網站,則Web Form就足以綽綽有餘了。若將來所要面對的是大公司或是大的網路專案,則MVC是不可避免的趨勢。
不過話又說回來,對於網路設計的基本知識一定要有,例如:HTML與Java Script 等的語法也要懂得。再來切入動態伺服器方面的網頁設計,學習起來會比較容易些。
但是,對於後起之秀MVC則有急起直追的趨勢,MVC是model,view,control 三者的簡稱。微軟在樣式與邏輯分離的控制層面上,似乎落後競爭對手許多,例如:Java ,Php 等知名軟體都在MVC上著墨一段時間。MVC 對於使用ASP.NET的人來說,是一種新的概念,故在設計與規劃上面,比起Web Form必須花費較多的時間在規畫上面,不過一旦完成規畫設計,對於後續的維護與擴充,則是Web Form所望塵莫及的。
然而,對於一個網頁學習者來說,究竟是先學 Web Form好呢?或者是直接學習MVC的架構。個人認為,視將來所要面對的工作環境做一個判斷準則。如果只是一般的小網站,則Web Form就足以綽綽有餘了。若將來所要面對的是大公司或是大的網路專案,則MVC是不可避免的趨勢。
不過話又說回來,對於網路設計的基本知識一定要有,例如:HTML與Java Script 等的語法也要懂得。再來切入動態伺服器方面的網頁設計,學習起來會比較容易些。
宣告事件二
如果每個事件的儲存開銷太大,我們可以在類別中包含事件存取宣告,按私有成員的規則存放事件控制碼列表。如下:
修飾子 event 型別識別字 {add { } ; remove { } ; }
上面的事件格式宣告,具有add , remove存取子,就像屬性宣告中的get ,set存取子一樣。
事件存取子的例子:
using System;
using System.Diagnostics;
namespace Event_test
{
//宣告一個delegate
public delegate void EventHandler( );
public class MyClass
{
//宣告一個成員變數來保存事件控制碼 (事件被觸發時被叫用的delegate)
private EventHandler m_Handler = null ;
//觸發事件
public void FireMyEvent( )
{
if (m_Handler != null )
{
m_Handler ( ) ;
}
}
//宣告事件存取子帶入委派所宣告的型別
public event EventHandler MyEvent
{
add //新增存取子
{
//注意,存取子中實際包含了一個名為value的隱含參數
//該參數的值即為客戶程式叫用 += 時傳遞過來的delegate
Console.WriteLine ("MyEvent add被叫用,value的HashCode為:" +
value.GetHashCode( ) );
//設置 m_Handler 域保持新的handler
if (value != null ) { m_Handler = value ; } ;
}
//刪除存取子
remove
{
Console.WriteLine ("MyEvent remove被叫用,value的HashCode為:" +
value.GetHashCode( ) );
//設置m_Handler為null,該事件不再被觸發
if ( value == m_Handler) { m_Handler = null ; }
}
}
}
public calss Program
{
//真正的事件處理函數
puiblic static void MyEventHandler( )
{
Console.WriteLine (" 這是一個事件被執行 ! ") ;
}
public static void Main( )
{
MyClass my = new MyClass ( ) ;
//基於MyEventHandler 函數定義一個EventHandler
EventHandler MyHandler = new EventHandler(MyEventHandler );
Console.WriteLine (" MyHandler of HashCode is: " + MyHandler.GetHashCode ( ) ) ;
Console.WriteLine ("----------------------------------------------------------------------------------") ;
//預訂事件
Console.WriteLine ("my.MyEvent += MyHandler 被叫用 ") ;
my.MyEvent += MyHandler ;
//觸發事件
Console.WriteLine ("Main 函數觸發 my 的 MyEvent 事件 ") ;
my.FireMyEvent ( ) ;
//撤銷事件
Console.WriteLine ("my.MyEvent -= MyHandler 被叫用 ") ;
my.MyEvent -= MyHandler ;
Console.WriteLine ("----------------------------------------------------------------------------------") ;
//再次試圖觸發事件
Console.WriteLine ("Main 函數試圖在撤銷事件後觸發 my 的 MyEvent 事件 ") ;
my.FireMyEvent ( ) ;
所以我們可以知道,當 Main 函數叫用my.FireMyEvent ( )時,my的m_Handler被叫用,也就是我們的MyEventHandler被叫用,所以會輸出 " 這是一個事件被執行 ! "。
修飾子 event 型別識別字 {add { } ; remove { } ; }
上面的事件格式宣告,具有add , remove存取子,就像屬性宣告中的get ,set存取子一樣。
事件存取子的例子:
using System;
using System.Diagnostics;
namespace Event_test
{
//宣告一個delegate
public delegate void EventHandler( );
public class MyClass
{
//宣告一個成員變數來保存事件控制碼 (事件被觸發時被叫用的delegate)
private EventHandler m_Handler = null ;
//觸發事件
public void FireMyEvent( )
{
if (m_Handler != null )
{
m_Handler ( ) ;
}
}
//宣告事件存取子帶入委派所宣告的型別
public event EventHandler MyEvent
{
add //新增存取子
{
//注意,存取子中實際包含了一個名為value的隱含參數
//該參數的值即為客戶程式叫用 += 時傳遞過來的delegate
Console.WriteLine ("MyEvent add被叫用,value的HashCode為:" +
value.GetHashCode( ) );
//設置 m_Handler 域保持新的handler
if (value != null ) { m_Handler = value ; } ;
}
//刪除存取子
remove
{
Console.WriteLine ("MyEvent remove被叫用,value的HashCode為:" +
value.GetHashCode( ) );
//設置m_Handler為null,該事件不再被觸發
if ( value == m_Handler) { m_Handler = null ; }
}
}
}
public calss Program
{
//真正的事件處理函數
puiblic static void MyEventHandler( )
{
Console.WriteLine (" 這是一個事件被執行 ! ") ;
}
public static void Main( )
{
MyClass my = new MyClass ( ) ;
//基於MyEventHandler 函數定義一個EventHandler
EventHandler MyHandler = new EventHandler(MyEventHandler );
Console.WriteLine (" MyHandler of HashCode is: " + MyHandler.GetHashCode ( ) ) ;
Console.WriteLine ("----------------------------------------------------------------------------------") ;
//預訂事件
Console.WriteLine ("my.MyEvent += MyHandler 被叫用 ") ;
my.MyEvent += MyHandler ;
//觸發事件
Console.WriteLine ("Main 函數觸發 my 的 MyEvent 事件 ") ;
my.FireMyEvent ( ) ;
//撤銷事件
Console.WriteLine ("my.MyEvent -= MyHandler 被叫用 ") ;
my.MyEvent -= MyHandler ;
Console.WriteLine ("----------------------------------------------------------------------------------") ;
//再次試圖觸發事件
Console.WriteLine ("Main 函數試圖在撤銷事件後觸發 my 的 MyEvent 事件 ") ;
my.FireMyEvent ( ) ;
所以我們可以知道,當 Main 函數叫用my.FireMyEvent ( )時,my的m_Handler被叫用,也就是我們的MyEventHandler被叫用,所以會輸出 " 這是一個事件被執行 ! "。
宣告事件一
例:
public delegate void DoGreeting(string name);
public class ManagerHello
{
//宣告一個事件
public event DoGreeting MakeGreet;
public void GreetHello(string name)
{
MakeGreet(name);
}
}
如上的程式碼,這個事件封裝了委派型別的變數,使得在類別的內部,不管是宣告它是public還是protected型別,它還是private型別。宣告一個事件類別似於宣告一個進行了封裝的委派型別變數。以下為叫用程式碼:
public void Main()
{
ManagerHello manager=new ManagerHello();
manager.MakerGreet += EnglishGreeting;
manager.MakerGreet += ChineseGreeting;
manager.GreetHello("張三");
}
這裡需注意的是:manager.MakerGreet += EnglishGreeting 語法只能寫成"+="(事件的註冊) 或是 "-="(事件的註銷)兩種形式,而不能寫成"="的形式,否則編譯器會回報錯誤。
public delegate void DoGreeting(string name);
public class ManagerHello
{
//宣告一個事件
public event DoGreeting MakeGreet;
public void GreetHello(string name)
{
MakeGreet(name);
}
}
如上的程式碼,這個事件封裝了委派型別的變數,使得在類別的內部,不管是宣告它是public還是protected型別,它還是private型別。宣告一個事件類別似於宣告一個進行了封裝的委派型別變數。以下為叫用程式碼:
public void Main()
{
ManagerHello manager=new ManagerHello();
manager.MakerGreet += EnglishGreeting;
manager.MakerGreet += ChineseGreeting;
manager.GreetHello("張三");
}
這裡需注意的是:manager.MakerGreet += EnglishGreeting 語法只能寫成"+="(事件的註冊) 或是 "-="(事件的註銷)兩種形式,而不能寫成"="的形式,否則編譯器會回報錯誤。
委派的宣告
在C#中,委派延伸於基底類別System.Delegate,但委派與一般類別的定義方法並不相同,委派通過關鍵字 delegate 來定義,例如:
public delegate void DoGreeting(string name);
即宣告一個新委派,它帶有一個string型別參數的方法。接個我們宣告一個叫 GreetHello的方法,如下:
public void GreetHello(string name, DoGreeting MakeGreeting)
{
MakeGreeting(name);
}
我們發現,委派DoGreeting出現的位置與string相同。string是一個類別,所以DoGreeting應該也是一個類別或叫型別。我們可以這麼解釋委派,委派是同樣也是一個類別,它是針對方法所定義該方法的型別可以取代如if-else或是swich等語法,避免大量使用判斷語法造成程式大而無當的現象產生,這種動態地將方法型別設定與參數的做法,可以使程式具有更好的擴展性。範例如下:
using System;
namespace test_delegate
{
//定義委派,它定義了可以代表的方法的類型
// EnglishGreeting or ChineseGreeting
public delegate void DoGreeting(string name); //宣告委派
public class Program
{
private static void EnglishGreeting(string name)
{
Console.WriteLine("Hello, " + name);
}
private static void ChineseGreeting(string name)
{
Console.WriteLine("你好, " + name);
}
//它接收一個DoGreeting型別的方法做為參數
//World 名稱
//委派(EnglishGreeting or ChineseGreeting)
private static void GreetHello(string name,DoGreeting MakeGreeting) //帶入委派(在方法 之前)
{
MakeGreeting(name); //此方法須傳入name參數,做為判斷是那一個型別是 EnglishGreeting或是ChineseGreeting型別
}
public static void Main()
{
GreetHello("Jim",EnglishGreeting); //執行GreetHello方法,是EnglishGreeting型別
GreetHello("張三",ChineseGreeting); //執行GreetHello方法,是ChineseGreeting型別
}
}
}
public delegate void DoGreeting(string name);
即宣告一個新委派,它帶有一個string型別參數的方法。接個我們宣告一個叫 GreetHello的方法,如下:
public void GreetHello(string name, DoGreeting MakeGreeting)
{
MakeGreeting(name);
}
我們發現,委派DoGreeting出現的位置與string相同。string是一個類別,所以DoGreeting應該也是一個類別或叫型別。我們可以這麼解釋委派,委派是同樣也是一個類別,它是針對方法所定義該方法的型別可以取代如if-else或是swich等語法,避免大量使用判斷語法造成程式大而無當的現象產生,這種動態地將方法型別設定與參數的做法,可以使程式具有更好的擴展性。範例如下:
using System;
namespace test_delegate
{
//定義委派,它定義了可以代表的方法的類型
// EnglishGreeting or ChineseGreeting
public delegate void DoGreeting(string name); //宣告委派
public class Program
{
private static void EnglishGreeting(string name)
{
Console.WriteLine("Hello, " + name);
}
private static void ChineseGreeting(string name)
{
Console.WriteLine("你好, " + name);
}
//它接收一個DoGreeting型別的方法做為參數
//World 名稱
//委派(EnglishGreeting or ChineseGreeting)
private static void GreetHello(string name,DoGreeting MakeGreeting) //帶入委派(在方法 之前)
{
MakeGreeting(name); //此方法須傳入name參數,做為判斷是那一個型別是 EnglishGreeting或是ChineseGreeting型別
}
public static void Main()
{
GreetHello("Jim",EnglishGreeting); //執行GreetHello方法,是EnglishGreeting型別
GreetHello("張三",ChineseGreeting); //執行GreetHello方法,是ChineseGreeting型別
}
}
}
2015年12月14日 星期一
漫步在C# 物件的簡單描述
身為一個程式設計師,選擇C#這條路就該毅然決然的走下去,沒有遲疑與後悔。在眾多科技語言的抉擇裡,既然選擇了你,就代表一生將與你為伴。觀念的釐清使用的時機與演算法的搭配,都是經驗一點一滴的累積。回歸主體,什麼叫物件,物件具有屬性(attritube)與方法(operation)兩大基本特性:
- 屬性:例如高矮胖瘦的具體描述,所顯示的顏色是紅色黃色或是藍色等之類,可以清楚的指出讓人可以馬上知道外型的輪廓、名稱等描述。比較屬於靜態方式的表示。
- 方法 :指出物件所動態作用,如速度的計算、高度的計算,數字的加總等,模擬實體所產生的動作過程與結果等,屬於動態方式的表示。
訂閱:
文章 (Atom)