<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    飛艷小屋

    程序--人生--哲學(xué)___________________歡迎艷兒的加入

    BlogJava 首頁(yè) 新隨筆 聯(lián)系 聚合 管理
      52 Posts :: 175 Stories :: 107 Comments :: 0 Trackbacks

    ?

    引用類型是類型安全的指針,它們的內(nèi)存是分配在堆(保存指針地址)上的。
    String、數(shù)組、類、接口和委托都是引用類型。
    強(qiáng)制類型轉(zhuǎn)換與as類型轉(zhuǎn)換的區(qū)別:當(dāng)類型轉(zhuǎn)換非法時(shí),強(qiáng)制類型轉(zhuǎn)換將拋出一個(gè)System.InvalidCastException異常,
    而as不會(huì)拋出異常,它返回一個(gè)null值。
    用using創(chuàng)建別名:using console = System.Console;
    訪問限定符:
    public? 該成員可以被其他任何類訪問
    protected 該成員只能被其派生類訪問
    private? 該成員只能被本類的其他成員訪問
    internal 該成員只能在當(dāng)前編譯單元的其他成員訪問
    帶參數(shù)列表和返回值的Main方法:
    class Test
    {
    ? public static int Main(string[] args)
    ? {
    ??? foreach (string arg in args)
    ??? {
    ??? ...
    ??? }
    ? }
    }
    構(gòu)造函數(shù)(constructor)包括實(shí)例構(gòu)造函數(shù)和靜態(tài)構(gòu)造函數(shù)。
    構(gòu)造函數(shù)與類名相同,且不能有返回值。例:
    class TestClass
    {
    ? TestClass()? //實(shí)例構(gòu)造函數(shù):可以訪問靜態(tài)成員和實(shí)例成員,用于初始化實(shí)例成員
    ? {
    ? ...
    ? }

    ? static TestClass() //靜態(tài)構(gòu)造函數(shù):只能訪問靜態(tài)成員,用于初始化靜態(tài)成員
    ? {
    ? ...
    ? }
    }
    類的靜態(tài)成員屬于類所有,不必生成實(shí)例就可以訪問,它是在載入包含類的應(yīng)用程序時(shí)創(chuàng)建的,
    但靜態(tài)方法不能訪問類的實(shí)例變量和方法。通常,靜態(tài)變量是在定義時(shí)就賦初始值的。
    類的實(shí)例成員屬于類的實(shí)例所有,不創(chuàng)建實(shí)例對(duì)象就無法對(duì)其進(jìn)行訪問,實(shí)例成員可以訪問類的
    靜態(tài)成員和其它實(shí)例成員。
    調(diào)用基類的析構(gòu)函數(shù):
    class A
    {
    ? public A()
    ? {
    ? ...
    ? }
    }
    class B
    {
    ? public B(): base()? //調(diào)用基類的析構(gòu)函數(shù)
    ? {
    ? ...
    ? }
    }
    常量:其值是在編譯時(shí)設(shè)定的,必須是數(shù)值文字。默認(rèn)狀態(tài)下常量是靜態(tài)的。例:
    class A
    {
    ? public const double pi = 3.1415;
    }
    常量是編譯時(shí)就確定的值,只讀字段是在運(yùn)行才能確定的值。比如運(yùn)行時(shí)才能確定的屏幕分辨率。
    只讀字段只能在類的析構(gòu)函數(shù)中賦值。
    靜態(tài)只讀字段:
    class A
    {
    ? public static readonly int ScreenWidth;? //靜態(tài)只讀字段
    ? static A()?? //靜態(tài)析構(gòu)函數(shù)
    ? {
    ??? ScreenWidth = 1024;? //在靜態(tài)析構(gòu)函數(shù)中初始化
    ? }
    }
    在類的繼承中,類的析構(gòu)函數(shù)是不會(huì)被繼承的。
    一個(gè)派生類只能從一個(gè)基類繼承,不能同時(shí)從多個(gè)基類繼承,但可以通過繼承多個(gè)接口來
    達(dá)到相同目的。實(shí)現(xiàn)多繼承的唯一方法就是使用接口。例:
    class MyFancyGrid: Control, ISerializable, IDataBound
    {
    ...
    }
    密封類是不能繼承的類,抽象類不能被定義為密封類,且密封類的私有成員不能用protected修飾,
    只能用private。例:
    sealed class A
    {
    ...
    }
    關(guān)鍵字ref和out用于指定用引用方式傳遞方法的參數(shù)。
    它們的區(qū)別是:ref參數(shù)必須初始化,而out參數(shù)不需要初始化。所以在方法處理代碼依賴參數(shù)的
    初始化值時(shí)使用ref,不依賴初始化值時(shí)使用out。
    對(duì)out參數(shù)即使在傳遞前對(duì)其進(jìn)行了初始化,其值也不會(huì)傳遞到方法處理函數(shù)內(nèi)部。傳遞時(shí)系統(tǒng)
    會(huì)將其設(shè)為未初始化。所以在方法內(nèi)部必須對(duì)out參數(shù)進(jìn)行初始化。
    方法重載時(shí),必須參數(shù)數(shù)目和參數(shù)類型其中之一不同,返回值不同不能作為重載。
    C#不支持方法的默認(rèn)值,只能通過方法重載來實(shí)現(xiàn)。例:
    class A
    {
    ? int Method(int a)
    ? {
    ? ...
    ? }

    ? void Method(int a, int b) //參數(shù)數(shù)目不同
    ? {??? //返回值不同不能作為重載
    ? ...
    ? }
    }
    params參數(shù)用于一個(gè)不定數(shù)目參數(shù)的方法,一般后面跟一個(gè)數(shù)組。例:
    class A
    {
    ? public void Method(params int[] i)
    ? {
    ? ...
    ? }
    }
    方法的覆蓋:指派生類覆蓋基類的同名方法,有二種方法
    1)第一種是在派生類要覆蓋的方法前面加new修飾,而基類不需要作任何改動(dòng)。
    這種方法的缺點(diǎn)是不能實(shí)現(xiàn)多態(tài)。例:
    class A
    {
    ? public void Method()? //無需任何修飾
    ? {
    ? ...
    ? }
    }

    class B: A?? //從基類繼承
    {
    ? new public void Method() //覆蓋基類的同名方法
    ? {
    ? ...
    ? }
    }

    class TestClass
    {
    ? A Instance = new B();
    ? Instance.Method();? //這時(shí)將調(diào)用類A的Method方法,而不是類B的Method方法
    }

    2)第二種是在派生類要覆蓋的方法前面加override修飾,而基類的同名方法前面加virtual修飾。
    這樣就能實(shí)現(xiàn)多態(tài),例:

    class A
    {
    ? virtual public void Method()?? //基類定義虛方法
    ? {????? //虛擬方法不能定義為private,因?yàn)閜rivate成員對(duì)派生類是無法訪問的
    ? ...
    ? }
    }

    class B: A???? //從基類繼承
    {
    ? override public void Method()?? //派生類覆蓋基類的同名虛方法
    ? {
    ? ...
    ? }
    }

    class TestClass
    {
    ? protected void Test()
    ? {
    ??? A Instance = new B();?? //定義一個(gè)實(shí)例,類型為基類,從派生類創(chuàng)建
    ????? //派生類總是能夠向上轉(zhuǎn)換為其基類
    ??? Instance.Method();??? //將調(diào)用派生類B的Method方法,而不是基類的,這就是多態(tài)
    ? }
    }

    說明:new修飾的方法覆蓋不能實(shí)現(xiàn)多態(tài)的原因,是因?yàn)槭褂胣ew時(shí)編譯器只會(huì)實(shí)現(xiàn)早期綁定(early binding)。
    即調(diào)用的方法在編譯時(shí)就決定了:編譯器看到Instance.Method()而Instance的類是A,就會(huì)調(diào)用類A的Method()方法。
    override修飾的方法覆蓋可以實(shí)現(xiàn)多態(tài)的原因,是因?yàn)閷?shí)現(xiàn)了后期綁定(late binding)。
    使用override時(shí)強(qiáng)制編譯器在運(yùn)行時(shí)根據(jù)類的真正類型正確調(diào)用相應(yīng)的方法,而不是在編譯時(shí)。
    而基類的同名方法必須加virtual修飾。
    類的靜態(tài)方法可能通過 類名.靜態(tài)方法名 這種格式來調(diào)用,不能使用 實(shí)例名.靜態(tài)方法名 這種方法調(diào)用。
    因?yàn)轭惖撵o態(tài)方法為類所有(是屬于類本身的),而非實(shí)例所有(不是屬于類的實(shí)例的)。
    類的靜態(tài)方法可以訪問類的任何靜態(tài)成員,但不能訪問類的實(shí)例成員。
    C#中類的變量稱為字段。類的public變量稱為類的公共字段。
    類的屬性由一個(gè)protected(也可以是private)字段和getter和setter方法構(gòu)成:
    class Address
    {
    ? protected string zipCode; //protected字段,注意大小寫
    ? public string ZipCode
    ? {
    ??? get??? //getter方法
    ??? {
    ????? return zipCode;
    ??? }
    ??? set??? //setter方法
    ??? {
    ????? zipCode = value;? //被傳遞的值自動(dòng)被在這個(gè)value變量中
    ??? }
    ? };
    }
    只讀屬性是指省略setter方法的屬性,只讀屬性只能讀取,不能設(shè)置。
    屬性也可以用限定符virtual,override和abstract修飾,功能同其他類的方法。
    屬性有一個(gè)用處稱為懶惰的初始化(lazy initialization)。即在需要類成員時(shí)才對(duì)它們進(jìn)行
    初始化。如果類中包含了很少被引用的成員,而這些成員的初始化又會(huì)花費(fèi)大量的時(shí)候和系統(tǒng)
    資源的話,懶惰的初始化就很有用了。
    C#中數(shù)組對(duì)象共同的基類是System.Array。
    將數(shù)組聲明為類的一個(gè)成員時(shí),聲明數(shù)組與實(shí)例化數(shù)組必須分開,這是因?yàn)橹荒茉谶\(yùn)行時(shí)創(chuàng)建了
    類的實(shí)例對(duì)象之后,才能實(shí)例化數(shù)組元素值。
    聲明:
    int[] intArray;? //一維數(shù)組
    int[,,] int3Array; //三維數(shù)組
    初始化:
    intArray = new int[3] {1,2,3};
    int[,] int2Array = new int[2,3] {{1,2,3},{4,5,6}}; //聲明時(shí)可以初始化
    遍歷:
    1)一維數(shù)組
    for (int i = 0; i < intArray.Length; i++); //Array.Length返回?cái)?shù)組所有元素的個(gè)數(shù)
    foreach (int i in intArray);
    for (int i = 0; i < intArray.GetLength(0); i++);//Array.GetLength(0)返回?cái)?shù)組第一維的個(gè)數(shù)
    2)多維數(shù)組
    for (int i = 0; i < int3Array.GetLength(0); i++) //遍歷三維數(shù)組
    ? for (int j = 0; j < int3Array.GetLength(1); j++)
    ??? for (int k = 0; k < int3Array.GetLength(2); k++)
    ??? {
    ??? ...
    ??? }
    數(shù)組的維數(shù)就是該數(shù)組的秩(Rank)。Array.Rank可以返回?cái)?shù)據(jù)的秩。
    鋸齒數(shù)組(jagged Array)是元素為數(shù)組的數(shù)組,例:
    int[][] jaggedArray = new int[2][]; //包含二個(gè)元素,每個(gè)元素是個(gè)數(shù)組
    jaggedArray[0] = new int[2];? //每個(gè)元素必須初始化
    jaggedArray[1] = new int[3];
    for (int i = 0; i < jaggedArray.Length; i++) //遍歷鋸齒數(shù)組
    ? for (int j = 0; j < jaggedArray[i].Length; j++)
    ? {
    ? ...
    ? }
    類的屬性稱為智能字段,類的索引器稱為智能數(shù)組。由于類本身作數(shù)組使用,所以用
    this作索引器的名稱,索引器有索引參數(shù)值。例:
    using System;
    using System.Collections;
    class MyListBox
    {
    ? protected ArrayList data = new ArrayList();
    ? public object this[int idx]? //this作索引器名稱,idx是索引參數(shù)
    ? {
    ??? get
    ??? {
    ????? if (idx > -1 && idx < data.Count)
    ????? {
    ??????? return data[idx];
    ????? }
    ????? else
    ????? {
    ??????? return null;
    ????? }
    ??? }
    ??? set
    ??? {
    ????? if (idx > -1 && idx < data.Count)
    ????? {
    ??????? data[idx] = value;
    ????? }
    ????? else if (idx = data.Count)
    ????? {
    ??????? data.Add(value);
    ????? }
    ????? else
    ????? {
    ??????? //拋出一個(gè)異常
    ????? }
    ??? }
    ? }
    }
    接口是二段不同代碼之間約定,通過約定實(shí)現(xiàn)彼此之間的相互訪問。
    C#并不支持多繼承,但通過接口可實(shí)現(xiàn)相同功能。
    當(dāng)在接口中指定了實(shí)現(xiàn)這個(gè)接口的類時(shí),我們就稱這個(gè)類“實(shí)現(xiàn)了該接口”或“從接口繼承”。
    一個(gè)接口基本上就是一個(gè)抽象類,這個(gè)抽象類中除了聲明C#類的其他成員類型——例如屬性、
    事件和索引器之外,只聲明了純虛擬方法。
    接口中可以包含方法、屬性、索引器和事件——其中任何一種都不是在接口自身中來實(shí)現(xiàn)的。例:
    interface IExampleInterface
    {
    ? //property declaration
    ? int testProperty { get; }

    ? //event declaration
    ? event testEvevnt Changed;

    ? //mothed declaration
    ? function void testMothed();

    ? //indexer declaration
    ? string this[int index] { get; set; }
    }
    說明:定義接口時(shí),在方法、屬性、事件和索引器所有這些接口成員都不能用public之類的訪問限定符,
    因?yàn)樗薪涌诔蓡T都是public類型的。
    因?yàn)榻涌诙x了一個(gè)約定,任何實(shí)現(xiàn)一個(gè)接口的類都必須定義那個(gè)接口中每一個(gè)成員,否則將編譯失敗。例:
    using System;
    public class FancyControl
    {
    ? protected string data;
    ? public string Data
    ? {
    ??? get {return this.data;}
    ??? set {data = value;}
    ? }
    }

    interface IValidate
    {
    ? bool Validate(); //接口方法
    }

    public class MyControl: FancyControl, IValidate
    {
    ? public MyControl()
    ? {
    ??? data = "my control data";
    ? }

    ? public bool Validate()? //實(shí)現(xiàn)接口
    ? {
    ??? if (data == "my control data")
    ????? return true;
    ??? else
    ????? return false;
    ? }
    }
    class InterfaceApp
    {
    ? MyControl myControl = new MyControl();
    ?
    ? IValidate val = (IValidate)myControl;? //可以將一個(gè)實(shí)現(xiàn)某接口的類,轉(zhuǎn)換成該接口
    ? bool success = val.Validate();? //然后可調(diào)用該接口的方法
    }
    也可以用:
    bool success = myControl.Validate();
    這種方法來調(diào)用Validate方法,因?yàn)閂alidate在類MyControl中是被定義成public的,如果去除public,Validate方法被隱藏,
    就不能用這種方法調(diào)用了,這樣隱藏接口方法稱為名字隱藏(name hiding)。
    可以用:類實(shí)例 is 接口名 來判斷某個(gè)類是否實(shí)現(xiàn)了某接口,例:
    myControl is IValidate? //MyControl類的實(shí)例myControl是否實(shí)現(xiàn)了IValidate接口
    當(dāng)然,也可用as來作轉(zhuǎn)換,根據(jù)轉(zhuǎn)換結(jié)果是否為null來判斷某個(gè)類是否實(shí)現(xiàn)了某接口,例:
    IValidate val = myControl as IValidate;
    if (null == val)
    {
    ...? //沒有實(shí)現(xiàn)IValidate接口
    }
    else
    {
    ...? //實(shí)現(xiàn)了IValidate接口
    }

    如果一個(gè)類從多個(gè)接口繼承,而這些接口中如果定義的同名的方法,則實(shí)現(xiàn)接口的方法時(shí),必須加接口名來區(qū)別,
    寫成 接口名.方法名。假設(shè)Test類從IDataStore和ISerializable二個(gè)接口繼承,而這二個(gè)接口都有SaveData()方法,
    實(shí)現(xiàn)SaveData()方法時(shí)必須寫成:
    class Test: ISerializable, IDataStore
    {
    ? void ISerializable.SaveData()
    ? {
    ? ...
    ? }

    ? void IDataStore.SaveData()
    ? {
    ? ...
    ? }
    }

    如果一個(gè)類從多個(gè)接口繼承,為了方便可以定義一個(gè)新的接口,這個(gè)接口繼續(xù)多個(gè)接口,然后類直接從這個(gè)接口繼承就
    可以了,這個(gè)叫合并接口。例:
    interface ISaveData: ISerializable, IDataStore
    {? //不需要定義任何方法或成員,只是用作合并
    }
    class Test: ISaveData? //只要繼承ISaveData就可以了
    {
    ...
    }
    C# 操作符優(yōu)先級(jí)(從高到低)
    初級(jí)操作符 () x.y f(x) a[x] x++ x-- new typeof sizeof checked unchecked
    一元操作符 + - | ~ ++x --x (T)x
    乘除操作符 * / %
    加減操作符 + -
    位移操作符 << >>
    關(guān)系操作符 < > <= >= is
    等于操作符 ==
    邏輯與? &
    邏輯異或 ^
    邏輯或? |
    條件與? &&
    條件或? ||
    條件操作符 ?:
    賦值操作符 = *= /= %= += -= <<= >>= &= ^= |=
    所有的二元操作符除賦值符外都是左聯(lián)合的,即從左到右計(jì)算。
    typeof()運(yùn)算符可以從一個(gè)類名得到一個(gè)System.Type對(duì)象,而從System.Object對(duì)象繼承來的GetType()方法
    則可從一個(gè)類實(shí)例來得到一個(gè)System.Type對(duì)象。例:
    Type t1 = typeof(Apple); //Apple是一個(gè)類名
    Apple apple = new Apple(); //apple是Apple類的一個(gè)實(shí)例
    Type t2 = apple.GetType(); //t1與t2是相同的
    通過反射得到一個(gè)類的所有成員和方法:
    Type t = typeof(Apple);
    string className = t.ToString(); //得到類名
    MethodInfo[] methods = t.GetMethods(); //得到所有方法
    foreach (MethodInfo method in methods)
    {
    //用method.ToString()得到方法名
    }
    MemberInfo[] members = t.GetMembers(); //得到所有成員
    foreach (MemberInfo member in members)
    {
    //用member.ToString()得到成員名
    }
    sizeof()操作符用來計(jì)算值類型變量在內(nèi)存中占用的字節(jié)數(shù)(Bytes),并且它只能在unsafe(非安全)
    代碼中使用。例:
    static unsafe public void ShowSizes()
    {
    ? int i, j;
    ? j = sizeof(short);
    ? j = sizeof(i);
    }
    盡可能使用復(fù)合賦值操作符,它比不用復(fù)合賦值操作符的效率高。
    for語(yǔ)句的語(yǔ)法為:
    for (initialization; Boolean-expression; step)
    ? embedded-statement
    在initialization和step部份還可以使用逗號(hào)操作符,例:
    for (int i = '0', j = 1; i <= '\xFF'; i++, j++)
    for (int i = 1, j = 1; i < 1000; i += j, j = i - j) //輸出斐波那契數(shù)列
    ?Console.Write("{0} ", i);
    在switch語(yǔ)句中執(zhí)行一個(gè)分支的代碼后還想執(zhí)行另一個(gè)分支的代碼,可以用:
    goto case 分支;
    操作符重載是為了讓程序更加自然,容易理解。想要為一個(gè)類重新定義一個(gè)操作符,使用以下語(yǔ)法:
    public static 返回值 operator 操作符 (操作對(duì)象1[,操作對(duì)象2])
    說明:
    1)所有重載的操作符方法都必須定義為public和static
    2)從技術(shù)上說返回值可以是任何類型,但通常是返回所定義方法使用的類型
    3)操作對(duì)象的數(shù)目取決于重載是一元操作符還是二元操作符,一元操作符只要一個(gè)操作對(duì)象,二元操作符則需要二個(gè)。
    4)不管重載是一元操作符還是二元操作符,第一個(gè)操作對(duì)象的類型都必須與返回值的類型一致;而對(duì)于二元操作符的第二個(gè)
    操作對(duì)象的類型則可以是任何類型。
    5)只有下列操作符可以被重載:
    一元:+ - ! ~ ++ -- true false
    二元:+ - * / % & | ^ << >> == != > < >= <=
    賦值操作符(+=,-=,*-,/=,%=等等)無法被重載。
    []和()操作符也無法被重載。
    6)操作符的優(yōu)先級(jí)是無法改變的,運(yùn)算優(yōu)先級(jí)的規(guī)則是靜態(tài)的。

    例:假設(shè)一個(gè)Invoice發(fā)票類由多個(gè)InvoiceDetailLine類(成員只有一個(gè)Double類型的Amount金額屬性)組成,
    我們重載+操作符,使之可以將InvoiceDetailLine類的內(nèi)容(注意不是金額合計(jì))加在一起。
    class Invoice
    {
    ? public ArrayList DetailLine;
    ?
    ? public Invoice?? //類的析構(gòu)函數(shù)
    ? {
    ??? DetailLine = new ArrayList(); //ArrayList存放多個(gè)InvoiceDetailLine類的實(shí)例
    ? }

    ? public static Invoice operator+ (Invoice Invoice1, Invoice Invoice2) //參數(shù)與返回值的類型一致
    ? {
    ??? //Invoice1與Invoice2的內(nèi)容合并
    ??? Invoice ReturnInvoice = new Invoice();
    ??? foreach(InvoiceDetailLine detailLine in Invoice1.DetailLines)
    ????? ReturnInvoice.DetailLine.Add(detailLine);
    ??? foreach(InvoiceDetailLine detailLine in Invoice2.DetailLines)
    ????? ReturnInvoice.DetailLine.Add(detailLine);
    ??? return ReturnInvoice;
    ? }
    }

    class InvoiceAddApp? //調(diào)用示例
    {
    ? public static void main()
    ? {
    ??? Invoice i1 = new Invoice();
    ??? for(int i = 0; i < 3; i++)
    ????? i1.DetailLine.Add(new InvoiceDetailLine(i + 1));

    ??? Invoice i2 = new Invoice();
    ??? for(int i = 0; i < 3; i++)
    ????? i2.DetailLine.Add(new InvoiceDetailLine(i + 1));

    ??? Invoice summaryInvoice = i1 + i2;? //調(diào)用重載的操作符+方法
    ? }
    }


    自定義類型轉(zhuǎn)換可以編寫代碼實(shí)際二個(gè)不同的類、結(jié)構(gòu)體之間的轉(zhuǎn)換。
    語(yǔ)法:public static implicite/explicite operator 輸出類型 (輸入類型)
    說明:
    1)轉(zhuǎn)換方法必須是靜態(tài)的。
    2)implicite表示隱式轉(zhuǎn)換,explicite表示顯式轉(zhuǎn)換。
    3)輸入類型和輸出類型其中之一必須與包含轉(zhuǎn)換的類或結(jié)構(gòu)體類型。即轉(zhuǎn)換必須與本類相關(guān)。
    例:
    struct Celisus
    {
    ? public float t;

    ? public Celisus(float t)
    ? {
    ??? this.t = t;?? //this.t是結(jié)構(gòu)體的字段,t是參數(shù)
    ? }

    ? public static implicite operator Celisus(float t) //float=>Celisus
    ? {
    ??? return new Celisus(t);
    ? }

    ? public static implicite operator float(Celisus c) //Celisus=>float
    ? {
    ??? return ((c.t - 32) / 9) * 5;
    ? }
    }


    代表的(delegate)目的與C++中的函數(shù)指針相同,代表不是在編譯時(shí)被定義的,而是在運(yùn)行時(shí)被定義的。
    代表主要有二個(gè)用途:回調(diào)(Callback)和事件處理(event)
    回調(diào)通常用于異步處理和自定義處理。例:
    class DBManager
    {
    ? static DBConnection[] activeConnections;
    ? //聲明回調(diào)函數(shù)
    ? public void delegate EnumConnectionCallback(DBConnection connection);

    ? public static void EnumConnections(EnumConnectionCallback callback)
    ? {
    ??? foreach (DBConnection connection in activeConnections)
    ??? {
    ????? callback(connection);? //執(zhí)行回調(diào)函數(shù)
    ??? }
    ? }
    }

    //調(diào)用
    class DelegateApp
    {
    ? public static void ActiveConncetionCallback(DBConnection connection) //處理函數(shù)
    ? {
    ? ...
    ? }

    ? public void main()
    ? {
    ??? //創(chuàng)建指向具體處理函數(shù)的代表實(shí)例(新建一個(gè)代表,讓它指向具體的處理函數(shù))
    ??? DBManager.EmnuConnectionCallback myCallback = new DBManager.EmnuConnectionCallback(ActiveConncetionCallback);
    ??? DBManager.EnumConnections(myCallback);
    ? }
    }

    //使用靜態(tài)代表,上面的調(diào)用改為
    class DelegateApp
    {
    ? //創(chuàng)建一個(gè)指向處理函數(shù)的靜態(tài)代表
    ? public static DBManager.EmnuConnectionCallback myCallback
    ??? = new DBManager.EmnuConnectionCallback(ActiveConncetionCallback);
    ? public static void ActiveConncetionCallback(DBConnection connection)
    ? {
    ? ...
    ? }

    ? public void main()
    ? {
    ??? DBManager.EnumConnections(myCallback);
    ? }
    }

    //在需要時(shí)才創(chuàng)建代表,上面的調(diào)用改為
    class DelegateApp
    {
    ? //將創(chuàng)建代表放在屬性的getter方法中
    ? public static DBManager.EmnuConnectionCallback myCallback
    ? {
    ??? get
    ??? {
    ????? retun new DBManager.EmnuConnectionCallback(ActiveConncetionCallback);
    ??? }
    ? }
    ? public static void ActiveConncetionCallback(DBConnection connection)
    ? {
    ? ...
    ? }

    ? public void main()
    ? {
    ??? DelegateApp app = new DelegateApp(); //創(chuàng)建應(yīng)用程序
    ??? DBManager.EnumConnections(myCallback);
    ? }
    }


    可以將多個(gè)代表整合成單個(gè)代表,例:
    class CompositeDelegateApp
    {
    ? public static void LogEvent(Part part)
    ? {
    ? ...
    ? }

    ? public static void EmailPurchasingMgr(Part part)
    ? {
    ? ...
    ? }

    ? public static void Main()
    ? {
    ??? //定義二個(gè)代表
    ??? InventoryManager.OutOfStockExceptionMethod LogEventCallback
    ????? = new InventoryManager.OutOfStockExceptionMethod(LogEvent);
    ??? InventoryManager.OutOfStockExceptionMethod EmailPurchasingMgrCallback
    ????? = new InventoryManager.OutOfStockExceptionMethod(EmailPurchasingMgr);
    ??? //整合為一個(gè)代表,注意后加的代表先執(zhí)行(這里是先執(zhí)行LogEventCallback)
    ??? InventoryManager.OutOfStockExceptionMethod onHandExceptionEventsCallback
    ????? = EmailPurchasingMgrCallback + LogEventCallback;
    ??? //調(diào)用代表
    ??? InventoryManager mgr = new InventoryManager();
    ??? mgr.ProcessInventory(onHandExceptionEventsCallback);
    ??? //InventoryManager類的ProcessInventory方法的原型為:
    ??? //public void ProcessInventory(OutOfStockExceptionMethod exception);
    ? }
    }

    可以根據(jù)需要將多個(gè)代表自由地組合成單個(gè)代表,例:
    class CompositeDelegateApp
    {
    ? //代表指向的處理函數(shù)(三個(gè)代表三個(gè)函數(shù))
    ? public static void LogEvent(Part part)
    ? {
    ? ...
    ? }

    ? public static void EmailPurchasingMgr(Part part)
    ? {
    ? ...
    ? }

    ? public static void EmailStoreMgr(Part part)
    ? {
    ? ...
    ? }

    ? public static void Main()
    ? {
    ??? //通過數(shù)組定義三個(gè)代表
    ??? InventoryManager.OutOfStockExceptionMethod[] exceptionMethods
    ????? = new InventoryManager.OutOfStockExceptionMethod[3];
    ??? exceptionMethods[0] = new InventoryManager.OutOfStockExceptionMethod(LogEvent);
    ??? exceptionMethods[1] = new InventoryManager.OutOfStockExceptionMethod(EmailPurchasingMgr);
    ??? exceptionMethods[2] = new InventoryManager.OutOfStockExceptionMethod(EmailStoreMgr);

    ??? int location = 1;
    ??? //再定義一個(gè)代表(用于組合成單代表)
    ??? InventoryManager.OutOfStockExceptionMethod compositeDelegate;
    ??? //根據(jù)需要組合
    ??? if (location = 2)
    ??? {
    ????? compositeDelegate = exceptionMethods[0] + exceptionMethods[1];
    ??? }
    ??? else
    ??? {
    ????? compositeDelegate = exceptionMethods[0] + exceptionMethods[2];
    ??? }
    ??? //調(diào)用代表
    ??? InventoryManager mgr = new InventoryManager();
    ??? mgr.ProcessInventory(compositeDelegate);
    ? }
    }
    C#的事件遵循“發(fā)布——預(yù)訂”的設(shè)計(jì)模式。在這種模式中,一個(gè)類公布能夠出現(xiàn)的所有事件,
    然后任何的類都可以預(yù)訂這些事件。一旦事件產(chǎn)生,運(yùn)行環(huán)境就負(fù)責(zé)通知每個(gè)訂戶事件已經(jīng)發(fā)生了。
    當(dāng)代表作為事件的處理結(jié)果時(shí)(或者說定義具有代表的事件),定義的代表必須指向二個(gè)參數(shù)的方法:
    一個(gè)參數(shù)是引發(fā)事件的對(duì)象(發(fā)布者),另一個(gè)是事件信息對(duì)象(這個(gè)對(duì)象必須從EventArgs類中派生)。
    例:
    using System;

    class InventoryChangeEventArgs: EventArgs //事件信息對(duì)象,從EventArgs類派生
    {
    ... //假設(shè)定義二個(gè)public屬性string Sku和int Change
    }

    class InventoryManager??? //事件的發(fā)布者
    {
    ? //聲明代表
    ? public delegate void InventoryChangeEventHander(object source, InventoryChangeEventArgs e);
    ? //發(fā)布事件,event關(guān)鍵字可將一個(gè)代表指向多個(gè)處理函數(shù)
    ? public event InventoryChangeEventHandler onInventoryChangeHander;
    ?
    ? public void UpdateInventory(string sku, int change)
    ? {
    ??? if (change == 0)
    ????? return;
    ??? InventoryChangeEventArgs e = new InventoryChangeEventArgs(sku, change);
    ??? //觸發(fā)事件
    ??? if (onInventoryChangeHandler != null) //如果有預(yù)訂者就觸發(fā)
    ????? onInventoryChangeHandler(this, e); //執(zhí)行代表指向的處理函數(shù)
    ? }
    }

    class InventoryWatcher??? //事件的預(yù)訂者
    {
    ? public InventoryWatcher(InventoryManager mgr) //mgr參數(shù)用于聯(lián)結(jié)發(fā)布者
    ? {
    ??? this.inventoryManager = mgr;
    ??? //預(yù)訂事件,用 += 調(diào)用多個(gè)處理函數(shù)
    ??? mgr.onInventroyChangeHandler += new InventoryManager.InventoryChangeEventHandler(onInventoryChange);
    ??? //事件處理函數(shù)
    ??? void onInventroyChange(object source, InventroyChangeEventArgs e)
    ??? {
    ??? ...
    ??? }

    ??? InventoryManager inventoryManager;
    ? }
    }

    class EventsApp???? //主程序
    {
    ? public static void Main()
    ? {
    ??? InventoryManager inventoryManager = new InventoryManager();
    ??? InventoryWatcher inventoryWatcher = new InventoryWatcher(inventoryManager);

    ??? inventoryManager.UpdateInventory("111 006 116", -2);
    ??? inventoryManager.UpdateInventory("111 006 116", 5);
    ? }
    }


    Microsoft Windows NT和IBM OS/2等操作系統(tǒng)都支持占先型多任務(wù)。在占先型多任務(wù)執(zhí)行中,處理器負(fù)責(zé)
    給每個(gè)線程分配一定量的運(yùn)行時(shí)間——一個(gè)時(shí)間片(timeslice)。處理器接著在不同的線程之間進(jìn)行切換,
    執(zhí)行相應(yīng)的處理。在單處理器的計(jì)算機(jī)上,并不能真正實(shí)現(xiàn)多個(gè)線程的同時(shí)運(yùn)行,除非運(yùn)行在多個(gè)處理器
    的計(jì)算機(jī)上。操作系統(tǒng)調(diào)度的多線程只是根據(jù)分配給每個(gè)線程時(shí)間片進(jìn)行切換執(zhí)行,感覺上就像同時(shí)執(zhí)行。

    上下文切換(context switching)是線程運(yùn)行的一部分,處理器使用一個(gè)硬件時(shí)間來判斷一個(gè)指定線程的時(shí)間片
    何時(shí)結(jié)束。當(dāng)這個(gè)硬件計(jì)時(shí)器給出中斷信號(hào)時(shí),處理器把當(dāng)前運(yùn)行的線程所用的所有寄存器(registers)數(shù)據(jù)
    存儲(chǔ)到堆棧中。然后,處理器把堆棧里那些相同的寄存器信息存放到一種被稱為“上下文結(jié)構(gòu)”的數(shù)據(jù)結(jié)構(gòu)中。
    當(dāng)處理器要切換回原來執(zhí)行的線程時(shí),它反向執(zhí)行這個(gè)過程,利用與該線程相關(guān)的上下文結(jié)構(gòu),在寄存器里
    重新恢復(fù)與這一線程相關(guān)的信息。這樣的一個(gè)完整過程稱為“上下文切換”。

    多線程允許應(yīng)用程序把任務(wù)分割為多個(gè)線程,它們彼此之間可以獨(dú)立地工作,最大限度地利用了處理器時(shí)間。

    using System;
    using System.Threading;

    class SimpleThreadApp
    {
    ? public static void WorkerThreadMethod() //線程的執(zhí)行體
    ? {
    ? ...????? //執(zhí)行一些操作
    ? }

    ? public static void Main()
    ? {
    ??? //創(chuàng)建一個(gè)線程代表指向線程的執(zhí)行體,ThreadStart是創(chuàng)建新線程必須用到的代表
    ??? ThreadStart worker = new ThreadStart(WorkerThreadMethod);
    ??? Thread t = new Thread(worker);? //用線程代表創(chuàng)建線程
    ??? t.Start();???? //執(zhí)行線程
    ? }
    }

    可以通過兩種方式來得到一個(gè)Thread對(duì)象:一種是通過創(chuàng)建一個(gè)新線程來得到,如上例;另一種在正在執(zhí)行的線程調(diào)用
    靜態(tài)的Thread.CurrentThread方法。
    靜態(tài)方法Thread.Sleep(int ms)可以讓當(dāng)前線程(它自動(dòng)調(diào)用Thread.CurrentThread)暫停指定毫秒的時(shí)間。
    如果使用Thread.Sleep(0)那么當(dāng)前線程將一直處于等待中,直到另一個(gè)線程調(diào)用這個(gè)線程的實(shí)例方法Thread.Interrupt方法,
    等待才會(huì)結(jié)束。
    使用Thread.Suspend方法也能掛起線程,Thread.Suspend方法可以被當(dāng)前線程或其他線程調(diào)用,而Thread.Sleep(0)
    只能由當(dāng)前線程在執(zhí)行體中調(diào)用。當(dāng)線程用Thread.Suspend掛起時(shí),必須用Thread.Resume方法恢復(fù)。不論Thread.Suspend
    方法調(diào)用了多少次,只要調(diào)用Thread.Resume方法一次就可以線程恢復(fù)執(zhí)行。用Thread.Suspend方法并不會(huì)阻塞線程,
    調(diào)用立即返回。而Thread.Sleep(0)則會(huì)阻塞線程。所以確切地說Thread.Sleep(0)暫停線程,而不是掛起線程。
    使用Thread.Abort方法可以終止正在執(zhí)行的線程。當(dāng)Thread.Abort方法被調(diào)用時(shí),線程不會(huì)立即終止執(zhí)行。運(yùn)行環(huán)境將會(huì)
    等待,直到線程到達(dá)文檔中所描述的“安全點(diǎn)”。如果要確保線程已經(jīng)完全停止,可以使用Thread.Join方法。這是一個(gè)同步
    調(diào)用,同步調(diào)用意味著直到線程完全停止,調(diào)用才會(huì)返回。
    Thread.Priority屬性用于設(shè)置的線程的優(yōu)先級(jí)。其值是Thread.ThreadPriority枚舉值,可以設(shè)為Highest, AboveNormal,
    Normal, BelowNormal, Lowest。缺省值是Thread.ThreadPriority.Normal。
    線程的同步是為了解決多個(gè)線程同時(shí)使用同一對(duì)象產(chǎn)生的一些問題。通過同步,可以指定代碼的臨界區(qū)(critical section),
    一次只有一個(gè)線程可以進(jìn)入臨界區(qū)。
    使用System.Monitor類(鎖定與信號(hào)量)進(jìn)行線程同步:
    using System;
    using System.Threading;

    public void SaveData(string text) //線程執(zhí)行函數(shù)或線程執(zhí)行函數(shù)調(diào)用的對(duì)象的方法
    {
    ? ...?? //執(zhí)行其他一些不需要同步的處理

    ? Monitor.Enter(this); //獲取對(duì)象的Monitor鎖
    ? ...?? //執(zhí)行需要同步的處理
    ? Monitor.Exit(this); //釋放對(duì)象的Monitor鎖

    ? ...?? //執(zhí)行其他一些不需要同步的處理
    }
    說明:當(dāng)執(zhí)行Monitor.Enter方法時(shí)。這個(gè)方法會(huì)試圖獲取對(duì)象上的Monitor鎖,如果另一個(gè)線程已經(jīng)擁有了
    這個(gè)鎖,這個(gè)方法將會(huì)阻塞(block),直到這個(gè)鎖被釋放。
    也可用C#的lock語(yǔ)句來獲得和釋放一個(gè)Monitor鎖。上面同步寫成:
    public void SaveData(string text) //線程執(zhí)行函數(shù)或線程執(zhí)行函數(shù)調(diào)用的對(duì)象的方法
    {
    ? ...?? //執(zhí)行其他一些不需要同步的處理

    ? lock(this)? //獲取對(duì)象的Monitor鎖,代碼塊執(zhí)行完成后釋放Monitor鎖
    ? {
    ? ...?? //執(zhí)行需要同步的處理
    ? }

    ? ...?? //執(zhí)行其他一些不需要同步的處理
    }

    也可以使用System.Threading名稱空間的Mutex類(互斥類)進(jìn)行線程同步。與Monitor鎖一樣,一次只有一個(gè)線程
    能獲得一個(gè)給定的互斥。但Mutex要慢得多,但它增加了靈活性。例:
    using System;
    using System.Threading;
    class Database
    {
    ? Mutex mutex = new Mutex(false); //創(chuàng)建一個(gè)互斥,但不立即獲得它
    ???? //注意:創(chuàng)建互斥在需要同步的方法之外,實(shí)際上它只要?jiǎng)?chuàng)建一個(gè)實(shí)例
    ? public void SaveData(string text) //需要同步的方法
    ? {
    ??? mutex.WaitOne();? //等待獲得互斥
    ??? ...??? //需要同步的處理
    ??? mntex.Close();? //釋放互斥
    ? }
    }

    Mutex類重載了三個(gè)構(gòu)造函數(shù):
    Mutex()?????? //創(chuàng)建并使創(chuàng)建類立即獲得互斥
    Mutex(bool initiallyOwned)??? //創(chuàng)建時(shí)可指定是否要立即獲得互斥
    Mutex(bool initiallyOwned, string muterName)? //還可以指定互斥的名稱
    Mutex.WaitOne方法也重載了三次:
    Mutex.WaitOne()????? //一直等待
    Mutex.WaitOne(TimeSpan time, bool exitContext)? //等待TimeSpan指定的時(shí)間
    Mutex.WaitOne(int milliseconds, bool exitContext) //等待指定的毫秒
    線程的用法:
    1)并發(fā)操作:比如一個(gè)程序監(jiān)視多個(gè)COM口,當(dāng)每個(gè)COM接到信息時(shí)執(zhí)行一段處理時(shí)。
    2)復(fù)雜長(zhǎng)時(shí)間操作:一個(gè)長(zhǎng)時(shí)間的復(fù)雜操作可能會(huì)使界面停滯,停止用戶響應(yīng),如果還允許用戶停止它,
    或者顯示進(jìn)度條、顯示操作執(zhí)行進(jìn)程信息時(shí)。
    反射(Reflection)就是能夠在運(yùn)行時(shí)查找類型信息,這是因?yàn)?NET編譯的可執(zhí)行(PE)文件中包括MSIL和元數(shù)據(jù)(metadata)。
    反射的中心是類System.Type。System.Type是一個(gè)抽象類,代表公用類型系統(tǒng)(Common Type System, CTS)中的一種類型。
    using System;
    using System.Reflection; //反射命名空間,必須引用

    public static void Main(string[] args)
    {
    ? int i = 6;
    ? Type t = i.GetType();?? //根據(jù)實(shí)例得到類型
    ? t = Type.GetType("System.Int32"); //根據(jù)類型的字符名稱得到類型
    }

    通過Assembly類可以得到已經(jīng)編譯.NET Framework程序的中所有類型,例:
    using System;
    using System.Diagnostics;? //為了使用Process類
    using System.Reflection;? //為了使用Assembly類

    class GetTypesApp
    {
    ? protected static string GetAssemblyName(string[] args)
    ? {
    ??? string assemblyName;
    ??? if (0 == args.Length) //如果參數(shù)為空,取當(dāng)前進(jìn)程的名稱
    ??? {
    ????? Process p = Process.GetCurrentProcess();
    ????? assemblyName = p.ProcessName + ".exe";
    ??? }
    ??? else
    ????? assemblyName = args[0]; //取第一個(gè)參數(shù),即當(dāng)前運(yùn)行程序名

    ??? return assemblyName;
    ? }

    ? public static void Main(string[] args)
    ? {
    ??? string assemblyName = GetAssemblyName(args);
    ??? Assembly a = Assembly.LoadFrom(assemblyName); //調(diào)用編譯程序集
    ??? Type[] types = a.GetTypes();?? //得到多個(gè)類型
    ??? foreach (Type t in types)??? //遍歷類型數(shù)組
    ??? {
    ??? ...? //取得t.FullName,t.BaseType.FullName等類型信息
    ??? }
    ? }
    }
    一個(gè)應(yīng)用程序可以包括多個(gè)代碼模塊。若要將一個(gè)cs文件編譯一個(gè)模塊,只要執(zhí)行下面的命令:
    csc /target:module 要編譯的模塊.cs? //csc是C Sharp Compiler(C#編譯器)
    然后在應(yīng)用程序中using編譯的模塊.cs中的NameSpace即可應(yīng)用了。
    要反射應(yīng)用程序中所有代碼模塊(Module),只要:
    Assembly a = Assembly.LoadFrom(assemblyName); //應(yīng)用程序的物理文件名
    Module[] modules = a.GetModules();
    foreach(Module m in modules)
    {
    ... //顯示m.Name等
    }
    后期綁定(latebinding),例:
    string[] fileNames = Directory.GetFiles(Environment.CurrentDirectory, "*.dll");
    foreach (string fileName in fileNames)
    {
    ? Assembly a = Assembly.LoadFrom(fileName);
    ? Type[] types = a.GetTypes();
    ? foreach(Type t in types)
    ? {
    ??? if (t.IsSubclassOf(typeof(CommProtocol)))? //判斷是否有CommProtocol的派生類
    ??? {
    ????? object o = Activator.CreateInstance(t);? //生成實(shí)例
    ????? MethodInfo mi = t.GetMethod("DisplayName");
    ????? mi.Invoke(o, null);??? //調(diào)用方法
    ??? }
    ? }
    }
    //帶參數(shù)的例子
    namespace Programming_CSharp
    {
    ? using System;
    ? using System.Reflection;
    ?
    ? public class Tester
    ? {
    ??? public static void Main( )
    ??? {
    ????? Type t = Type.GetType("System.Math");
    ????? Object o = Activator.CreateInstance(t);

    ????? // 定義參數(shù)類型
    ????? Type[] paramTypes = new Type[1];
    ????? paramTypes[0]= Type.GetType("System.Double");

    ????? MethodInfo CosineInfo = t.GetMethod("Cos", paramTypes);

    ????? //設(shè)置參數(shù)數(shù)據(jù)
    ????? Object[] parameters = new Object[1];
    ????? parameters[0] = 45;

    ????? //執(zhí)行方法
    ????? Object returnVal = CosineInfo.Invoke(o, parameters);
    ????? Console.WriteLine("The cosine of a 45 degree angle {0}", returnVal);
    ??? }
    ? }
    }
    動(dòng)態(tài)生成代碼和動(dòng)態(tài)調(diào)用的完整例子:
    //動(dòng)態(tài)生成代碼的部分
    using System;
    using System.Reflection;
    using System.Reflection.Emit;? //動(dòng)態(tài)生成代碼必須引用

    namespace ILGenServer
    {
    ? public class CodeGenerator
    ? {
    ??? public CodeGenerator()
    ??? {
    ????? currentDomain = AppDomain.CurrentDomain;? //得到當(dāng)前域
    ????? assemblyName = new AssemblyName();? //從域創(chuàng)建一個(gè)程序集
    ????? assemblyName.Name = "TempAssembly";
    ????? //得到一個(gè)動(dòng)態(tài)編譯生成器,AssemblyBuilerAccess.Run表示只在內(nèi)存中運(yùn)行,不能保存
    ????? assemblyBuilder = currentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilerAccess.Run);
    ????? //從編譯生成器得到一個(gè)模塊生成器
    ????? moduleBuilder = assemblyBuilder.DefineDynamicModule("TempModule");
    ????? //模塊生成器得到類生成器
    ????? typeBuilder = moduleBuilder.DefineType("TempClass", TypeAttributes.Public);
    ????? //為類添加一個(gè)方法
    ????? methodBuilder = typeBuilder.DefineMethod("HelloWord", MethodAttributes.Public, null, null);
    ????? //為方法寫入代碼,生成代碼必須使用到IL生成器
    ????? msil = methodBuilder.GetILGenerator();
    ????? msil.EmitWriteLine("Hello World");
    ????? msil.Emit(OpCodes.Ret);
    ????? //最后還需要編譯(build)一下類
    ????? t = typeBuilder.CreateType();
    ??? }
    ??? AppDomain currentDomain;
    ??? AssemblyName assemblyName;
    ??? AssemblyBuilder assemblyBuilder;
    ??? ModuleBuilder moduleBuilder;
    ??? TypeBuilder typeBuilder;
    ??? MethodBuilder methodBuilder;
    ??? ILGenerator msil;
    ??? object o;
    ??? Type t;
    ??? public Type T
    ??? {
    ????? get
    ????? {
    ??????? return this.t;
    ????? }
    ??? }
    ? }
    }
    //動(dòng)態(tài)調(diào)用的部分
    using System;
    using System.Reflection;
    using ILGenServer;? //引用動(dòng)態(tài)生成代碼的類
    public class ILGenClientApp
    {
    ? public static void Main(
    ? {
    ??? CodeGenerator gen = new CodeGenerator(); //創(chuàng)建動(dòng)態(tài)生成類
    ??? Type t = gen.T;
    ??? if (null != t)
    ??? {
    ????? object o = Activator.CreateInstance(t);
    ????? MethodInfo helloWorld = t.GetMethod("HelloWorld"); //為調(diào)用方法創(chuàng)建一個(gè)MethodInfo
    ????? if (null != helloWorld)
    ????? {
    ??????? helloWorld.Invoke(o, null);? //調(diào)用方法
    ????? }
    ??? }
    ? }
    }
    調(diào)用DLL
    using System;
    using System.Runtime.InteropServices; //為了使用DLLImport特性

    class PInvokeApp
    {
    ? [DllImport("user32.dll", CharSet=CharSet.Ansi)] //CharSet.Ansi指定Ansi版本的函數(shù)(MessageBoxA),CharSet.Unicode指定Unicode版本的函數(shù) (MessageBoxW)
    ? static extern int MessageBox(int hWnd, string msg, string caption, int type);? //聲明DLL中的函數(shù)
    ?
    ? //[DllImport("user32.dll", EntryPoint="MessageBoxA")] //用這種方法使用不同的函數(shù)名
    ? //static extern int MsgBox(int hWnd, string msg, string caption, int type);
    ?
    ? //[DllImport("user32.dll", CharSet=CharSet.Unicode)]? //調(diào)用Unicode版的DLL函數(shù)
    ? //static extern int MessageBox(int hWnd, [MarshalAs(UnmanagedType.LPWStr)]string msg,
    ? // [MarshalAs(UnmanagedType.LPWStr)]string caption, int type); //將LPWStr翻譯為string型,缺省情況系統(tǒng)只將LPStr翻譯成string
    ? public static void Main()
    ? {
    ??? MessageBox(0, "Hello, World!", "CaptionString", 0);? //調(diào)用DLL中的函數(shù)
    ? }
    }
    例2,使用回調(diào):
    class CallbackApp
    {
    ? [DllImport("user32.dll")]
    ? static extern int GetWindowText(int hWnd, StringBuilder text, int count);

    ? delegate bool CallbackDef(int hWnd, int lParam);

    ? [DllImport("user32.dll")]
    ? static extern int EnumWindows(CallbackDef callback, int lParam);

    ? static bool PrintWindow(int hWnd, int lParam)
    ? {
    ??? StringBuilder text = new StringBuilder(255);
    ??? GetWindowText(hWnd, text, 255);
    ??? Console.WriteLine("Window Caption: {0}", text);
    ??? return true;
    ? }

    ? static void Main()
    ? {
    ??? CallbackDef callback = new CallbackDef(PrintWindow);
    ??? EnumWindows(callback, 0);
    ? }
    }
    關(guān)鍵字unsafe指定標(biāo)記塊在非控環(huán)境中運(yùn)行。該關(guān)鍵字可以用于所有的方法,包括構(gòu)造函數(shù)和屬性,
    甚至還有方法中的代碼塊。關(guān)鍵字fixed負(fù)責(zé)受控對(duì)象的固定(pinning)。Pinning是一種動(dòng)作,向
    垃圾收集器(Garbage Collector, GC)指定一些不能被移動(dòng)的對(duì)象。為了不在內(nèi)存中產(chǎn)生碎片,.NET
    運(yùn)行環(huán)境把對(duì)象四處移動(dòng),以便于最有效地利用內(nèi)存。使用fixed后指定對(duì)象將不會(huì)被移動(dòng),所以就
    可以用指針來訪問它。
    C#中只能得到值類型、數(shù)組和字符串的指針。在數(shù)組的情況下,第一個(gè)元素必須是值類型,因?yàn)镃#
    實(shí)際上是返回一個(gè)指向數(shù)組第一個(gè)元素的指針,而不是返回?cái)?shù)組自身。
    & 取一個(gè)變量的內(nèi)存地址(即指向該變量的指針)
    * 取指針?biāo)缸兞康闹?br />-> 取成員
    例:
    using System;
    class UnsafeApp
    {
    ? public static unsafe void GetValues(int* x, int* y)
    ? {
    ??? *x = 6;
    ??? *y = 42;
    ? }

    ? public static unsafe void Main()
    ? {
    ??? int a = 1;
    ??? int b = 2;
    ??? GetValues(&a, &b);
    ? }
    }
    fixed語(yǔ)法為:fixed(type* ptr = expression) statements
    其中type也可以為非控類型,也可是void;expression是任何產(chǎn)生一個(gè)type指針的表達(dá)式;
    statements是應(yīng)用的代碼塊。例:
    fixed (int* f = &foo.x)? //foo是Foo類的一個(gè)實(shí)例,x是Foo類的一個(gè)int屬性
    {
    ? SetFooValue(f);? //SetFooValue方法的定義為unsafe static void SetFooValue(int* x)
    }
    傳統(tǒng)的COM組件可以通過互操作層(COM Interop)與.NET運(yùn)行環(huán)境交互。互操作層處理在托管運(yùn)行環(huán)境和非托管區(qū)域
    中的COM組件操作之間傳遞所有的消息。
    要使COM組件能在.NET環(huán)境中使用,必須為COM組件生成元數(shù)據(jù)。.NET運(yùn)行環(huán)境用元數(shù)據(jù)層業(yè)判斷類型信息。在運(yùn)行時(shí)刻
    使用類型信息,以便生成RCW(Runtime Callable Wrapper,運(yùn)行時(shí)可調(diào)用包裝)。當(dāng).NET應(yīng)用程序與COM對(duì)象交互時(shí),
    RCW處理對(duì)COM對(duì)象的裝載和調(diào)用。RCW還完成許多其他的工作,如管理對(duì)象標(biāo)識(shí)、對(duì)象生存周期以及接口緩沖區(qū)。
    對(duì)象生存周期管理十分關(guān)鍵,因?yàn)?NET GC把對(duì)象到處移動(dòng),并且當(dāng)對(duì)象不再使用時(shí),自動(dòng)處理這些對(duì)象。RCW服務(wù)告訴
    .NET,應(yīng)用程序正與托管.NET組件交互,同時(shí)又使非托管COM組件“覺得”COM對(duì)象是被傳統(tǒng)的COM客戶端調(diào)用的。
    為了為COM組件生成元數(shù)據(jù)包裝,必須使用tlbimp.exe(TypeLib Importer)工具:
    tlbimp some_COM.tlb /out:som_COM.dll

    posted on 2007-01-14 20:18 天外飛仙 閱讀(576) 評(píng)論(0)  編輯  收藏 所屬分類: .net
    主站蜘蛛池模板: 99re在线这里只有精品免费| 亚洲另类无码专区首页| 亚洲av无码一区二区三区乱子伦| 国产精品亚洲mnbav网站 | 国产精品永久免费10000| 野花香高清视频在线观看免费| 成年女人A毛片免费视频| 一级特黄录像免费播放肥| 中文字幕免费在线看| 97在线免费视频| 久久久久久一品道精品免费看| 久久精品视频免费播放| 久久A级毛片免费观看| 日本最新免费网站| 毛片在线看免费版| 午夜网站免费版在线观看| 国产精品成人无码免费| 亚洲日本韩国在线| 亚洲国产精品久久久天堂| 亚洲精品中文字幕无码AV| 亚洲av永久无码精品三区在线4| 亚洲综合国产成人丁香五月激情 | 亚洲白嫩在线观看| 77777亚洲午夜久久多喷| 在线观看亚洲精品专区| 一级毛片aaaaaa视频免费看| 99久久国产精品免费一区二区 | 中国一级毛片视频免费看| 久久精品免费观看| 99久久久精品免费观看国产| 好吊妞788免费视频播放| 全部免费a级毛片| 久久亚洲综合色一区二区三区| 亚洲精品国产啊女成拍色拍| 色偷偷噜噜噜亚洲男人| 久久久久久噜噜精品免费直播 | a级毛片毛片免费观看久潮| 最近的中文字幕大全免费8 | 无码人妻久久一区二区三区免费 | baoyu777永久免费视频 | 日韩在线观看视频免费|