1. 程式人生 > >C# Delegate 簡介

C# Delegate 簡介

C# 是一個頗具爭議的新興語言,由 Microsoft 開發創造,以作為其 Visual Studio.NET 的基石,目前正處於第一個 Beta 版的釋出階段。C# 結合了源自 C++ 和 Java 的許多特性。Java 社群對 C# 主要的批評在於,其聲稱 C# 只是一個蹩腳的 Java 克隆版本 ——與其說它是語言創新的成果,倒不如說是一樁訴訟的結果。而在 C++ 社群裡,主要的批評(也同時針對 Java)是,C# 只不過是另一個泛吹濫捧的私有語言(yet another over-hyped proprietary language)。

本 文意在展示一種 C# 的語言特性,而在 C++ 或 Java 中都沒有直接支援類似的特性。這就是 C# 的 delegate 型別,其運作近似於一種指向成員函式的指標。我認為,C# delegate 型別是經過深思熟慮的創新型語言特性,C++ 程式設計師(無論其對 C# 或者 Microsoft 有何想法)應該會對這個特性產生特殊的興趣。

為了激發討論,我將圍繞一個 testHarness class 的設計來進行闡述。這個 testHarness class 能夠讓任何類別對 static 或 non-static 的 class methods 進行註冊,以便後續予以執行。Delegate 型別正是實現 testHarness class 的核心。

C# 的 Delegate Type
Delegate 是一種函式指標,但與普通的函式指標相比,區別主要有三:

1) 一個 delegate object 一次可以搭載多個方法(methods)[譯註1],而不是一次一個。當我們喚起一個搭載了多個方法(methods)的 delegate,所有方法以其“被搭載到 delegate object 的順序”被依次喚起——稍候我們就來看看如何這樣做。

2) 一個 delegate object 所搭載的方法(methods)並不需要屬於同一個類別。一個 delegate object 所搭載的所有方法(methods)必須具有相同的原型和形式。然而,這些方法(methods)可以即有 static 也有 non-static,可以由一個或多個不同類別的成員組成。

3) 一個 delegate type 的宣告在本質上是建立了一個新的 subtype instance,該 subtype 派生自 .NET library framework 的 abstract base classes Delegate 或 MulticastDelegate,它們提供一組 public methods 用以詢訪 delegate object 或其搭載的方法(methods)

宣告 Delegate Type
一 個 delegate type 的宣告一般由四部分組成:(a) 訪問級別;(b) 關鍵字 delegate;(c)返回型別,以及該 delegate type 所搭載之方法的宣告形式(signature);(d) delegate type 的名稱,被放置於返回型別和方法的宣告形式(signature)之間。例如,下面聲明瞭一個 public delegate type Action,用來搭載“沒有引數並具有 void 返回型別”的方法:

public delegate void Action();

一 眼看去,這與函式定義驚人的相似;唯一的區別就是多了 delegate 關鍵字。增加該關鍵字的目的就在於:要通過關鍵字(keyword)——而非字元(token)——使普通的成員函式與其它形似的語法形式區別開來。這樣 就有了 virtual,static, 以及 delegate 用來區分各種函式和形似函式的語法形式。

如果一個 delegate type 一次只搭載單獨一個方法(method),那它就可以搭載任意返回型別及形式的成員函式。然而,如果一個 delegate type 要同時搭載多個方法(methods),那麼返回型別就必須是 void[譯註2]。 例如,Action 就可以用來搭載一個或者多個方法(method)。在 testHarness class 實現中,我們就將使用上述的 Action 宣告。

定義 Delegate Handle
在 C# 中我們無法宣告全域性物件;每個物件定義必須是下述三種之一:區域性物件;或者型別的物件成員;或者函式引數列表中的引數。現在我只向你展示 delegate type 的宣告。之後我們再來看如何將其宣告為類別中的成員。

C# 中的 delegate type 與 class, interface, 以及 array types 一樣,屬於 reference type。每個 reference type 被分為兩部分:

一個具名的 控制代碼(named handle),由我們直接操縱;以及
一個該控制代碼所屬型別的不具名物件(unamed object),由我們通過控制代碼間接進行操縱。必須經由 new 顯式的建立該物件。
定義 reference type 是一個“兩步走”的過程。當我們寫:

Action theAction;

的 時候,theAction 代表“delegate type Action 之物件”的一個 handle(控制代碼),其本身並非 delegate object。預設情況下,它被設為 null。如果我們試圖在對其賦值(譯註:assigned,即與相應型別的物件做attachment)之前就使用它,會發生編譯期錯誤。例如,語句:

theAction();

會喚起 theAction 所搭載的方法(method(s))。然而,除非它在定義之後、使用之前被無條件的賦值(譯註:assigned,即與相應型別的物件做attachment),否則該語句會引發編譯期錯誤並印出相關資訊。

為 Delegate Object 分配空間
在 這一節中,為了以最小限度的涉及面繼續進行闡述,我們需要訪問一個靜態方法(static method)和一個非靜態方法(non-static method),就此我採用了一個 Announce class。該類別的 announceDate 靜態方法(static method)以 long form 的形式(使用完整單字的冗長形式)列印當前的日期到標準輸出裝置:

Monday, February 26, 2001

非靜態方法(non-static method) announceTime 以 short form 的形式(較簡短的表示形式)列印當前時間到標準輸出裝置:

00:58

前兩個數字代表小時,從午夜零時開始計算,後兩個數字代表分鐘。Announce class 使用了由 .NET class framework 提供的 DateTime class。Announce 類別的定義如下所示。

public class Announce
{
   public static void announceDate()
   {
      DateTime dt = DateTime.Now;
      Console.WriteLine( "Today''''s date is {0}",
                         dt.ToLongDateString() );
   }
   public void announceTime()
   {
      DateTime dt = DateTime.Now;
      Console.WriteLine( "The current time now is {0}",
                         dt.ToShortTimeString() );
   }
}

要 讓 theAction 搭載上述方法,我們必須使用 new 表示式建立一個 Action delegate type(譯註:即建立一個該類別的物件)。要搭載靜態方法,則傳入建構函式的引數由三部分組成:該方法所屬類別的名稱;方法的名稱;分隔兩個名稱用的 dot operator(.):

theAction = new Action( Announce.announceDate );

要搭載非靜態方法,則傳入建構函式的引數也由三部分組成:該方法所屬的類別物件名稱;方法的名稱;分隔兩個名稱用的 dot operator(.):

Announce an = new Announce();
theAction   = new Action( an.announceTime );

可 以注意到, theAction 被直接賦值,事先沒有做任何檢查(比如,檢查它是否已經指代一個堆中的物件,如果是,則先刪除該物件)。在 C# 中,存在於 managed heap(受託管的堆)中的物件由執行期環境對其施以垃圾收集動作(garbage collected)。我們不需要顯式的刪除那些經由 new 表示式分配的物件。

在程式的 managed heap(受託管的堆)中,new 表示式既可以為獨個物件做分配

HelloUser myProg = new HelloUser();

也可以為陣列物件做分配

string [] messages = new string[ 4 ];

分配語句的形式為:型別的名稱,後跟關鍵字 new,後跟一對圓括弧(表示單個物件)或者方括號(表示陣列物件)[1]。(在 C# 語言設計中的一個普遍特徵就是,堅持使用單一明晰的形式來區別不同的功用。)

一個快速的概覽:Garbage Collection(垃圾收集)
如下述陣列物件所示,當我們在 managed heap(受託管的堆)中為 reference type 分配了空間:

int [] fib = new int[6]{ 1,1,2,3,5,8 };

物件自動的維護“指向它的控制代碼(handles)”之數目。在這個例子中,被 fib 所指向的陣列物件有一個關聯的引用計數器被初始化為1。如果我們現在初始化另一個控制代碼,使其指向 fib 所指代的陣列物件:

int [] notfib = fib;

這次初始化導致了對 fib 所指代陣列物件的一次 shallow copy(淺層拷貝)。這就是說,notfib 現在也指向 fib 所指向的陣列物件。該陣列物件所關聯的引用計數變成了2。

如果我們經由 notfib 修改了陣列中某個元素,比如

notfib [ 0 ] = 0;

這個改變對於 fib 也是可見的。如果這種對同一個物件的多重訪問方式並非所需,我們就需要編寫程式碼,做一個 deep copy(深層拷貝)。例如,

// 分配另一個數組物件
notfib = new int [6];
// 從 notfib 的第0個元素開始,
// 依次將 fib 中的元素拷貝到 notfib 中去。
// 見註釋 [2]
fib.CopyTo( notfib, 0 );

notfib 現在並不指代 fib 所指代的那個物件了。先前被它們兩個同時指向的那個物件將其關聯的引用計數減去1。notfib 所指代物件的初始引用計數為1。如果我們現在也將 fib 重新賦值為一個新的陣列物件——例如,一個包含了Fibonacci數列前12個數值的陣列:

fib = new int[12]{ 1,1,2,3,5,8,13,21,34,55,89,144 };

對於之前被 fib 所指代的那個陣列物件,其現在的引用計數變成了0。在 managed heap(受託管的堆)中,當垃圾收集器(garbage collector)處於活動狀態時,引用計數為0的物件被其作上刪除標記。

定義 Class Properties
現在讓我們將 delegate object 宣告為 testHarness class 的一個私有靜態(private static)成員。例如 [3],

public class testHarness
{
   public delegate void    Action();
   static private Action theAction;
   // ...
}

下 一步我們要為這個 delegate 成員提供讀寫訪問機制。在 C# 中,我們不要提供顯式的內聯方法(inline methods)用來讀寫非公有的資料成員。取而代之,我們為具名的屬性(named property)提供 get 和 set 訪問符(accessors)。下面是個簡單的 delegate property。我們不妨將其稱為 Tester:

public class testHarness
{
   static public Action Tester
   {
      get{ return theAction; }
      set{ Action = value; }
   }
   // ...
}

Property(屬 性)既可以封裝靜態資料成員,也可以封裝非靜態資料成員。Tester 就是 delegate type Action 的一個 static property(靜態屬性)。(可以注意到。我們將 accessor 定義為一個程式碼區塊。編譯器內部由此產生 inline method。)

get 必須以 property(屬性)的型別作為返回型別。在這個例子中,其直接返回所封裝的物件。如果採用“緩式分配(lazy allocation)”,get 可以在初次被喚起的時候建構並存放好物件,以便後用。

類似的,如果我們希望 property(屬性)能夠支援寫入型訪問,我們就提供 set accessor。set 中的 value 是一個條件型關鍵字(conditional-keyword)。也就是說,value 僅在 set property 中具有預定義的含義(譯註:也就是說,value 僅在 set 程式碼段中被看作一個關鍵字):其總是代表“該 property(屬性)之型別”的物件。在我們的例子中,value 是 Action 型別的物件。在執行期間,其被繫結到賦值表示式的右側。在下面的例子中,

Announce an = new Announce();
testHarnes.Tester =
    new testHarness.Action
    ( an.announceTime );

set 以內聯(inline)的方式被展開到 Tester 出現的地方。value 物件被設定為由 new 表示式返回的物件。

喚起 Delegate Object
如之前所見,要喚起由 delegate 所搭載的方法,我們對 delegate 施加 call operator(圓括弧對):

testHarness.Tester();

這 一句喚起了Tester property 的 get accessor;get accessor返回 theAction delegate handle。如果 theAction 在此刻並未指向一個 delegate object,那麼就會有異常被丟擲。從類別外部實行喚起動作的規範做法(delegate-test-and-execute,先實現代理,再測試,最 後執行之)如下所示:

if ( testHarness.Tester != null )
   testHarness.Tester();

對於 testHarness class,我們的方法只簡單的封裝這樣的測試:

static public void run()
{
   if ( theAction != null )
      theAction();
}

關聯多個 Delegate Objects
要讓一個 delegate 搭載多個方法,我們主要使用 += operator 和 -= operator。例如,設想我們定義了一個 testHashtable class。在建構函式中,我們把各個關聯的測試加入到 testHarness 中:

public class testHashtable
{
   public void test0();
   public void test1();
   testHashtable()
   {
      testHarness.Tester += new testHarness.Action( test0 );
      testHarness.Tester += new testHarness.Action( test1 );
   }
   // ...
}

同樣,如果我們定義一個 testArrayList class,我們也在 default constructor 中加入關聯的測試。可以注意到,這些方法是靜態的。

public class testArrayList
{
   static public void testCapacity();
   static public void testSearch();
   static public void testSort();
   testArrayList()
   {
      testHarness.Tester += new
         testHarness.Action(testCapacity);
      testHarness.Tester += new testHarness.Action(testSearch);
      testHarness.Tester += new testHarness.Action(testSort);
   }
   // ...
}

當 testHarness.run 方法被喚起時,通常我們並不知道 testHashtable 和 testArrayList 中哪一個的方法先被喚起;這取決於它們建構函式被喚起的順序。但我們可以知道的是,對於每個類別,其方法被喚起的順序就是方法被加入 delegate 的順序。

Delegate Objects 與 Garbage Collection(垃圾收集)
考察下列區域性作用域中的程式碼段:

{
   Announce an = new Announce();
   testHarness.Tester +=
      new testHarness.Action
      ( an.announceTime );
}

當我們將一個非靜態方法加入到 delegate object 中之後,該方法的地址,以及“用來喚起該方法,指向類別物件的控制代碼(handle)”都被儲存起來。這導致該類別物件所關聯的引用計數自動增加。

an 經由 new 表示式初始化之後,managed heap(受託管的堆)中的物件所關聯的引用計數被初始化為1。當 an 被傳給 delegate object 的建構函式之後,Announce 物件的引用計數增加到2。走出區域性作用域之後,an 的生存期結束,該引用計數減回到1——delegate object還佔用了一個。

好訊息是,如果有一個 delegate 引用了某物件的一個方法,那麼可以保證該物件會直到“delegate object 不再引用該方法”的時候才會被施以垃圾收集處理[4]。我們不用擔心物件會在自己眼皮底下被貿然清理掉了。壞訊息是,該物件將持續存在(譯註:這可能是不 必要的),直到 delegate object 不再引用其方法為止。可以使用 -= operator 從 delegate object 中移除該方法。例如下面修正版本的程式碼;在區域性作用域中,announceTime 先被設定、執行,然後又從 delegate object 中被移除。

{
   Announce an = new Announce();
   Action act = new testHarness.Action( an.announceTime );
   testHarness.Tester += act;
   testHarness.run();
   testHarness.Tester -= act;
}

我 們對於設計 testHashtable class 的初始想法是,實現一個解構函式用以移除在建構函式中加入的測試用方法。然而,C# 中的解構函式呼叫機制與 C++ 中的卻不大相同[5]。C# 的解構函式既不會因為物件生存期結束而跟著被喚起,也不會因為釋放了物件最後一個引用控制代碼( reference handle)而被直接喚起。事實上,解構函式僅在垃圾收集器作垃圾收集時才被呼叫,而施行垃圾收集的時機一般是無法預料的,甚至可以根本就沒施行垃圾收 集。

C# 規定,資源去配動作被放進一個稱為 Dispose 的方法中完成,使用者可以直接呼叫該方法:

public void Dispose ()
{
   testHarness.Tester -= new testHarness.Action( test0 );
   testHarness.Tester -= new testHarness.Action( test1 );
}

如果某類別定義了一個解構函式,其通常都會喚起 Dispose。

訪問底層的類別介面
讓我們再回頭看看先前的程式碼:

{
   Announce an = new Announce();
   Action act =
       new testHarness.Action
       ( an.announceTime );
   testHarness.Tester += act;
   testHarness.run();
   testHarness.Tester -= act;
}

另一種實現方案是,先檢查 Tester 當前是否已經搭載了其它方法,如果是,則儲存當前的委託列表(delegation list),將 Tester 重置為 act,然後呼叫 run,最後將 Tester 恢復為原來的狀態。

我們可以利用底層的 Delegate 類別介面來獲知 delegate 實際搭載的方法數目。例如,

if ( testHarness.Tester != null &&
     testHarnest.GetInvocationList().Length != 0 )
   {
      Action oldAct = testHarness.Tester;
      testHarness.Tester = act;
      testHarness.run();
      testHarness.Tester = oldAct;
   }  
else { ... }

GetInvocationList 返回 Delegate class objects 陣列,陣列的每個元素即代表該 delegate 當前搭載的一個方法。Length 是底層 Array class 的一個 property(屬性)。Array class 實現了 C# 內建陣列型別的語義[6]。

經由 Delegate class 的 Method property,我們可以獲取被搭載方法的全部執行期資訊。如果方法是非靜態的,那麼經由 Delegate class 的 Target property,我們更可以獲取呼叫該方法之物件(譯註:即該方法所屬類別的那個物件)的全部執行期資訊。在下面例子中,Delegate 的 methods(方法) 和 properties(屬性)用紅色表示:

If (testHarness.Tester != null )
{
   Delegate [] methods = test.Tester.GetInvocationList();
   foreach ( Delegate d in methods )
   {
      MethodInfo theFunction = d.Method;
      Type       theTarget   = d.Target.GetType();
   // 好的:現在我們可以知道 delegate 所搭載方法的全部資訊
   }
}

總結
希 望本文能夠引起你對 C# delegate type 的興趣。我認為 delegate type 為 C# 提供了一種創新性的“pointer to class method(類別方法之指標)”機制。或許本文還引起了你對 C# 語言以及 .NET class framework 的興趣。

A good starting page for technical resources is <http://www.microsoft.com/net/>. An informative news group with Microsoft developer input dealing with both .NET and C# is <http://discuss.develop.com/dotnet.html>. Of course, questions or comments on C# or this article can be addressed to me at

[email protected] Finally, C# is currently in the process of standardization. On October 31, 2000, Hewlett-Packard, Intel, and Microsoft jointly submitted a proposed C# draft standard to ECMA, an international standards body (ECMA TC39/TG2). The current draft standard and other documentation can be found at <http://www.ecma.ch>.

致謝
I would like to thank Josee Lajoie and Marc Briand for their thoughtful review of an earlier draft of this article. Their feedback has made this a significantly better article. I would also like to thank Caro Segal, Shimon Cohen, and Gabi Bayer of you-niversity.com for providing a safety.NET.

註釋
[1] 對於 C++ 程式設計師來說,有兩點值得一題:(a) 需要在物件的型別名稱之後放一對圓括弧作為 default constructor,以及(b) 用於陣列下標的方括號要放在型別與陣列名稱之間。

[2] C# 中內建的陣列是一種由 .NET class library 提供的 Array class 之物件。Array class 的靜態方法和非靜態方法都可以被 C# 內建陣列物件使用。CopyTo 是 Array 的一個非靜態方法。

[3] 與 Java 一樣,C# 中的成員宣告包括其訪問級別。預設的訪問級別是 private。

[4] 類似的,C++ 標準要求,被引用的臨時物件必須直到引用的生存期結束時才能夠被銷燬。

[5] 在內部實現中,解構函式甚至都不曾存在過。一個類別的解構函式會被轉換成 virtual Finalize 方法。

[6] 在 C# 中,一個條件判別式的結果必須得到 Boolean 型別。對 Length 值的直接判別,如if(testHarness.Length),並不是合法的條件判斷。整型值無法被隱式的轉換為 Boolean 值。

Stanley B. Lippman is IT Program Chair with you-niversity.com, an interactive e-learning provider of technical courses on Patterns, C++, C#, Java, XML, ASP, and the .NET platform. Previously, Stan worked for over five years in Feature Animation both at the Disney and DreamWorks Animation Studios. He was the software Technical Director on the Firebird segment of Fantasia 2000. Prior to that, Stan worked for over a decade at Bell Laboratories. Stan is the author of C++ Primer, Essential C++, and Inside the C++ Object Model. He is currently at work on C# Primer for the DevelopMentor Book Series for Addison-Wesley. He may be reached at
[email protected]


譯註
[譯註1] 在C#中,所謂“method(方法)”,其實就是指我們平常所理解的成員函式,其字面意義與“function(函式)”非常接近。

[譯註2] 作者是就前述的那個 delegate type Action 宣告而有此言。就一般而言,只要多個方法(methods)的返回型別相同並且引數也相同,就可以被同一個 delegate type 搭載。

相關推薦

C# Delegate 簡介

C# 是一個頗具爭議的新興語言,由 Microsoft 開發創造,以作為其 Visual Studio.NET 的基石,目前正處於第一個 Beta 版的釋出階段。C# 結合了源自 C++ 和 Java 的許多特性。Java 社群對 C# 主要的批評在於,其聲稱 C# 只是

c# delegate ,event

賦值 () ear get alt 運算符 app all fun 首先說明,event其實也是一種delegate,為了區分,我們稱一般的delegate為“plain delegate”。寫代碼的過程中,經常會在delegate和event之間進行選擇,以前也沒仔細思考

C語言-簡介

運行環境 數組下標 ria sdn IT alt width 技術 可用 ????C語言是一門通用計算機編程語言,應用廣泛。C語言的設計目標是提供一種能以簡易的方式編譯、處理低級存儲器、產生少量的機器碼以及不需要任何運行環境支持便能運行的編程語言。最初是由丹尼斯·裏奇在貝爾

c# delegate和event

ima 靜下心來 不出 更多 部分 .com 運算符 你是 直接    一直誤以為event更多的比delegate多一個+= -=的運算符,沒想到在沒有event的關鍵字的情況下,delegate依然是可以用+=, -=運算符,這一下就尷尬了,於是靜下心來好好的研究了一

c# delegate action func predicate event 匿名函數 lambda

編寫 tel keyword AC 保存 word HA 沒有 上下文 1、delegate  是C#中的一種類型,它實際上是一個能夠持有對某個方法的引用的類。  與其它的類不同,delegate類能夠擁有一個簽名 (signature),並且它只能持有與它的簽名相匹配的方

C語言簡介

什麽 gist == register 忽略 而是 2個 關系運算符 精度 C語言僅有32個關鍵字,9種控制語句,34種運算符 數據類型關鍵字(12個) (1) char:聲明字符型變量或函數 (2) double:聲明雙精度變量或函數 (3)

C# 委託簡介

1.1官方解釋 委託是一種定義方法簽名的型別。當例項化委託時,您可以將其例項與任何具有相容簽名的方法相關聯。您可以通過委託例項呼叫方法。 1.2個人理解 委託就是執行方法(函式)的一個類。 事件是一種特殊的委託。 二、如何申明委託 2.1 delegate  &

C# Delegate 如何從子執行緒修改UI執行緒 主執行緒介面

一、為什麼Control類提供了Invoke和BeginInvoke機制? 關於這個問題的最主要的原因已經是dotnet程式設計師眾所周知的,我在此費點筆墨再次記錄到自己的日誌,以便日後提醒一下自己。 1、windows程式訊息機制 Windows GUI程式是

C# delegate的新的認識 關於型別轉換

public class Test{ public delegate void repeatRecall(); public repeatRecall finalCall; //最終呼叫 public List<repeatRecal

C語言簡介&FAQ

C語言是什麼 C語言是一種計算機程式語言。 1970年前後,AT&T 貝爾實驗室的 Ken Thompson根據BCPL語言設計出較先進的並取名為B的語言,之後Dennis Ritchie在此基礎上設計發明了C語言, 並首次在UNIX作

Poco C++庫簡介

學習一個框架前,要先明白它的是什麼,為什麼,怎麼用.下面這些文字,是從中文poco官網上轉過來的,正如poco c++庫的特點,非常清晰,程式碼風格更是一目瞭然.    poco開發庫的特點,非常適合寫後臺處理程式,效率也是很高的.前臺介面程式使用Qt框架庫,非常好,兩個庫

C++的簡介、起源與發展

1.C++簡介: C++融合了3種不同的程式設計方式:C語言代表的過程性語言、C++在C語言基礎上新增的類代表的面嚮物件語言、C++模板支援的泛型程式設計。 2.C++簡史: 2.1 C語言程式設計原理: 由於C++在C語言的基礎上移植了新的程式設計理念

【影象處理】HDF5 C++程式設計簡介

HDF5是一種科學資料格式,其特點是可以將不同型別的資料集整合儲存到一個檔案,並分別打上標籤、註釋。相比舊版的HDF格式,HDF5能支援大於4GB的檔案讀寫;HDF5在資料集的基礎上增加包Group,類似資料夾。這使得HDF5檔案內部像普通的檔案系統一樣,便於資

服務元件體系結構 C++ API 簡介

熟悉將用於 Apache Tuscany SCA for C++ 的 API。您將通過本文了解該 API 的主要組成部分,以便快速入門。   構建並連線簡單的 C++ 服務元件   關於 Tuscany   Apache Tuscany 是正處於孵化期的 Apache Sof

Pelles C編譯器簡介

簡介: 基於LCC的一款C編譯器,有標準的IDE介面,類似VC的介面,當然和DEV-C++還有MingW32 studio介面也很像,可以用於建立小一點的基於C的工程。 IDE程式碼編輯介面不太好看,不過可以根據自己的習慣設定的很漂亮。也可用notepad++,edit

c# Delegate 例子

  using System; using System.IO; using System.Text; using System.Collections.Generic; using System.Text.RegularExpressions; namespace Con

語言基礎(2):C++標準簡介

constant template 派生類 ont 虛函數 成員 color key 初始 1、C++98標準的主要特征 在C++98發布之時,已經具有類及派生類、共有和私有成員的區分、類的構造函數和析構函數、友元、內聯函數、賦值運算符的重載,虛函數的概念、函數和運算符的重

C++ 泛型程序設計與STL模板庫(1)---泛型程序設計簡介及STL簡介與結構

urn 向上 隊列 是把 鏈表 需要 input stack 特定 泛型程序設計的基本概念 編寫不依賴於具體數據類型的程序 將算法從特定的數據結構中抽象出來,成為通用的 C++的模板為泛型程序設計奠定了關鍵的基礎 術語:概念 用來界定具備一定功能的數據類型。例如:

C++重載運算簡介

... alua ast 認識 希望 ive his 輸入流 資源 本文基於《C++ Primer(第5版)》中14章和《More Effective C++》條款7,整理而成。 其實寫這篇博客之前,內心還是很忐忑的,因為,博主的水平很有限,視野比較窄,要是在理解書的過程中

.net/c#常用框架/中間件簡介

跨語言 bat 方法 entity 系統 wcf 序列 lpush 面向 任務調度 Quartz.NET:Quartz.NET是一個開源的作業調度框架,非常適合在平時的工作中,定時輪詢數據庫同步,定時郵件通知,定時處理數據等。 Quartz.NET允 許開發人員根