18个不常见的C#关键字,您使用过几个?
轉自:http://www.cnblogs.com/zhuqil/archive/2010/04/09/UnCommon-Csharp-keywords-A-Look.html
1、__arglist
??? 讓我們先從__arglist開始。 __arglist是用來給方法傳送參數。通常我們是通過函數頭部指定的參數列表給方法傳遞參數的。如果我們想要給方法傳遞一組新的參數,我們需要重載方法。如果我們想要傳遞的參數數量不確定,我們需要使用param數組。我們為什么要使用__arglist,因為上面兩種方法,存在的下面問題:
a、如果我們使用方法重載,一旦要傳遞一組新的參數,我們都要增加一個新的函數重載。
b、如果我們用param數組,參數類型必須相同或者使用param對象數組。
__arglist能解決上面的問題。你可以傳遞任何參數給函數,可以是任何類型,我們可以使用簡單的步驟分析每個參數。
讓我們先看下下面代碼:
1?public?int?paramLength(__arglist)2?{
3???????????ArgIterator?iterator?=?new?ArgIterator(__arglist);
4???????????return?iterator.GetRemainingCount();
5?}
如果我使用下面代碼調用該函數
1?int?x?=?this.paramLength(__arglist(49,34,54,6,"Manimoy"));?//?returns?5?將被返回5給變量x。這是因為我們給這個方法傳遞了5個參數。我們可以訪問每個參數,如:?
1?TypedReference?tf?=?iterator.GetNextArg();2?TypedReference.ToObject(tf)
每次調用GetNextArg,GetRemainingCount將減1,直到遍歷完迭代器的每個對象。
2、__refvalue?
另一個有趣的關鍵字是__refvalue。它是用來獲取一個引用對象的的值。你可以用來從TypedReference對象中獲得實際對象。這需要兩個參數,第一個就是TypedReference對象和另一個是轉換的類型。看看下面代碼:
1?int?tfValue?=?__refvalue(tf,?int);?3、__makeref
__makeref將使從對象中找出TypedReference對象。這跟_refvalue剛剛相反。請看下面的代碼:
1?string?name?=?"Ayan";2?TypedReference?tf?=?__makeref(name);
4、 __reftype
__reftype是用來從TypedReference類型的對象獲得類型。看下面代碼所示:
1?Type?t?=?__reftype(tf);2?if(t.ToString().equals("System.String"))
3?string?str?=?__refvalue(t,string);?
注:雖然我在所有的C#版本中發現上面這些關鍵字,但我沒在工作中使用它。在未來版本的C#可能不存在這些關鍵字,所以是否使用看你自己的風險。
5、Yield
??? Yield出現在.NET 2.0中,使用Yield將以枚舉數對象值的形式返回,yield 語句只能出現在iterator 塊中,該塊可用作方法、運算符或訪問器的體。在以下代碼中,我構建了一個名字列表,將返回長度小于5的名字列表,遇到yield break語句返回。
1?List<string>?lst?=?new?List<string>();?2?lst.Add("Abhishek");
?3?lst.Add("Abhijit");
?4?lst.Add("Manimoy");
?5?lst.Add("Raj");
?6?lst.Add("Ayan");
?7?lst.Add("MacMillanRojer");
?8?lst.Add("Rizzuto");
?9?foreach?(string?x?in?lst)
10?{
11????if?(x.Length?>?12)?//?Breaks?on?MacMillanRojer
12??????yield?break;
13????else?if?(x.Length?>?5)?//?Only?returns?those?which?are?having?length?>5
14??????yield?return?x;
15????else?continue;
16?}
17??
其實,yield return x 將判斷每個元素,并創建了滿足條件所有的元素的enumerable(length> 5)。
break語句將終止循環,并返回現有創建好的枚舉。
6、?Fixed
另一種不常見的關鍵字是Fixed,它只能在不安全的C#代碼塊中使用。Fixed語句在個固定的內存地址設置一個指針,它不會被移動到任何地方,即使執行了垃圾收集線程。讓我們來看看下面的代碼:
1??int[]?a?=?new?int[]?{?1,?2,?3?};2?fixed?(int*?pt?=?a)
3?{
4????int*?c?=?pt;
5????MessageBox.Show("Value?:?"?+?*c);
6????//?This?will?fix?the?variable?totally?so?that?it?will
7????//?not?be?moved?when?Garbage?collector?is?invoked.?
8?}
在這里,指針c和pt被分配相同的位置。Fixed通常會花銷一些資源。實際上它妨礙垃圾收集的正常進程。因此,實際中應該避免使用 fixed語句。
7、Checked / Unchecked?
??? 另一個名為checked的關鍵字是用來控制算術溢出的情況。當算術運算溢出時,Checked關鍵字拋出OverflowException異常。
??? 看下這段代碼:
1?int?x?=?int.MaxValue;2?int?y?=?int.MaxValue;
3?int?z?=?checked(x?+?y);??
??? 上述聲明中,當執行到x + y時,將拋出OverflowException異常。 checked用來檢查運算溢出并引發相應的異常。?當發生OverflowException異常時,z被賦值為0。
??? 當我們不需要拋出異常時,我們可以使用關鍵字unchecked。
1?int?x?=?int.MaxValue;2?int?y?=?int.MaxValue;
3?int?z?=?unchecked(x?+?y);
??? 通過執行上面的代碼,z的值將被賦值為-2。
8、Volatile?
volatile關鍵字用于定義一個變量,這個變量跨多個線程修改而不被lock(雖然我們大部分的時間鎖定它們)。 volatile變量不受編譯器優化,因此我們將獲得該變量的所有的時間最新的值。見下面的例子:
1?public?volatile?int?i;?2?Thread?th?=?new?Thread(new?ThreadStart(VolatileInvoke));
?3?th.Start();
?4?Thread.Sleep(5000);?//Holds?current?Thread?for?5?seconds.
?5?MessageBox.Show("Value?of?i?:?"?+?i);
?6?th.Abort();
?7?
?8?private?void?VolatileInvoke()
?9?{
10????while?(true)
11????{
12??????????i++;
13????}
14?}?
線程啟動,volatile整數的值增加1,直到它被主線程中止。
注意:Volatile類型沒有線程優化。
9、StackAlloc??
??? 在unsafe的C#代碼中使用,動態從堆棧分配內存。stackalloc用于快速獲取內存。當我們使用堆棧,我們可以利用內存快速存取的優勢。我們可以這樣聲明一個數組:
1?int*?array?=?stackalloc?new?int[1000]??注意:您應該始終牢記,stackalloc內存是非常有限的。它是由每個線程默認為1MB。因此,如果我們需要大量的內存(超過1MB),我們必須回到原來堆內存結構。
10、 Global ::?
??? 當想要用本地的命名空間隱藏的全局的命名空間,這個關鍵字是非常方便的。假設我們有我們的項目中創建了一個名為System的類,C#中是允許這樣做的。當我想使用全局的System空間時,我們必須使用global::.。讓我們來看看下面的例子:
1?internal?class?System?2?{
?3?????????internal?class?Array?:IEnumerable?
?4?????????{
?5?????????????public?int?Length
?6?????????????{
?7?????????????????get{return?1000}
?8?????????????}
?9?????????????#region?IEnumerable?Members
10?????????????public?IEnumerator?GetEnumerator()
11?????????????{
12?????????????????Debug.Write("This?is?Dummy?Array");
13?????????????????return?base.GetEnumerator();
14?????????????}
15?
16?????????????#endregion
17?????????}
18?}
??? 現在,如果你要調用System.Array它會調用一個本地定義。要調用全局的System,我們需要使用global::System。當你確定調用全局命名空間時,最好它始終使用global:: 。
11、Namespace/Class別名
我們使用using 來定義別名。有2種形式的別名:
a、Namespace別名:
當你想縮短比較長的命名空間時,可以使用命名空間的別名。
1?using?Abhishek?=?System.Drawing;2?public?class?X?
3?{
4??????public?X()
5??????{
6?????????Abhishek.Graphics?g?=?this.CreateGraphics();
7??????}
8?}??
在這里,我們為System.Drawing的定義了一個別名Abhishek 。因此,我們在代碼中引用Abhishek,與引用System.Drawing是相同的。
b、Class別名:
您也可以使用using語句來定義一個類引用。例如我寫:using Abhishek=System.Drawing.Bitmap;
Abhisek等同于Bitmap類。我們可以創建Abhishe的對象,直接訪問靜態函數。
1?using?Abhishek=System.Drawing.Graphics;2?public?class?X
3?{
4??????public?X()
5??????{
6?????????????Abhishek?g?=?this.CreateGraphics();
7??????}
8?}
因此,Abhishek將對應本機的Graphics對象而不是整個命名空間的。
12、extern別名?
我們使用C#工作,大多數時候需要引用外部控件集。
我們會遇到這樣的情況,在相同的應用程序中相同命名空間中添加兩個版本的dll時。在這種情況下,我們需要外部別名功能,來指定兩個不同的程序集。
例如:
假設我們添加一個程序集x10.dll(V1),其中有一Y類
我們添加x20.dll(V2),我們可能要使用Y類
首先,要參考完全合格的程序集,我們需要在命令行中聲明一個別名。
/r:XV1=X10.dll
/r:XV2=X20.dll?
現在參考我們的使用
1?extern?alias?XV1;2?extern?alias?XV2;
13、??
??與null值一起使用。在2.0中引入。看以下內容:
1?MyClass?x?=?null;2?x?=?x????new?MyClass();
??的意思是說,如果X是null 值,將new MyClass() ,否則將賦值現有的X值
14、@variables
??? 通常是C#不允許使用關鍵字做變量的。但是有一種方式例外。我們可以通過使用@創建與關鍵字具有相同的名稱的變量。
假設我們定義:
1?int?@int?=?10;這意味著聲明了一個名字為int的變量和并分配10給它。
15、Readonly
??? 目前,readonly是C#關鍵字,用來創建不能被程序修改的變量。該聲明為readonly的變量,變量的值將被分配一次,它將在整個對象執行過程中保持相同的值。
聲明一個只讀變量:
1?public?readonly?int?readonlyvariable?=?20;?聲明了一個值為20 的變量。再對這個變量賦值是不允許的。
16 、Const & readonly 的區別?
??? readonly類似關鍵字const。唯一不同的是, const 變量在編譯時定義的,readonly變量在運行時定義。您可以從內部構造函數中分配readonly變量的值,因此根據你的構造函數分配,readonly值可能不同。
1?public?readonly?int?readsecond;2?public?Documented()
3?{
4???????readsecond?=?DateTime.Now.Second;
5?}?
在這里,readsecond將根據對象的初始化指派不同的值,對于const這是不可能的。
17 、Default
??? 對于一般對象,關鍵字default非常方便。當對象未初始化,它返回的默認值。例如,如果沒有賦予任何值,我們都知道整數被初始化為0。當沒有賦任何值,字符串為空字符。當不指定任何值,對象為null。
這些值是根據default關鍵字分配。
因此,如果我們寫:
類似于:
int x;
一般情況下,當類型不確定時,我們可以使用default來分配特定的值給對象。讓我們看看該示例:
2?{
3??????return?default(T);
4?}?
該函數返回每個類型的默認值。從而
因此,我們可以使用關鍵字default非常容易獲取對象默認的分配的值。
1?int?defx?=?this.GetDefault<int>();?//will?assign?02?char?defy?=?this.GetDefault<char>();?//?will?assign?null('\0')
3?object?defz?=?this.GetDefault<object>();?//?will?assign?null
18、Nullable Types?
?? C#的Nullable類型可以處理空值甚至是基本數據類型。每個nullable類型是來自System.Nullable。我們可以這樣定義nullables:
1?int??nullableint?=?null;?這里nullableint將被賦值null。
如果您訪問nullable變量,您將獲得2個屬性。
HasValue屬性將返回false,如果null被分配給變量;
Value屬性返回變量的實際值。
您還可以使用每種nullable類型的對象的GetValueOrDefault函數來得到變量的默認值。
結論:
我的目的是給你一個簡短方式介紹一下這些關鍵字的知識,以及如何去使用它們。請隨意發表您的評論。
代碼點擊下載
PS:
1到4是Undocumented關鍵字,5到18是documented關鍵字。
如果覺得對你有點幫助,或者有點意思。請推薦一下,謝謝。
?
?
原文參考:UnCommon C# keywords - A Look?
作者:朱祁林
出處:http://zhuqil.cnblogs.com?
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。
總結
以上是生活随笔為你收集整理的18个不常见的C#关键字,您使用过几个?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 说说我的工作——桌面支持
- 下一篇: c# char unsigned_dll