1、__arglist
讓我們先從__arglist開始。 __arglist是用來給方法傳送參數。通常我們是通過函數頭部指定的參數列表給方法傳遞參數的。如果我們想要給方法傳遞一組新的參數,我們需要重載方法。如果我們想要傳遞的參數數量不確定,我們需要使用param數組。我們爲什麼要使用__arglist,因爲上面兩種方法,存在的下面問題:
a、如果我們使用方法重載,一旦要傳遞一組新的參數,我們都要增加一個新的函數重載。
b、如果我們用param數組,參數類型必須相同或者使用param對象數組。
__arglist能解決上面的問題。你可以傳遞任何參數給函數,可以是任何類型,我們可以使用簡單的步驟分析每個參數。
讓我們先看下下面代碼:
2 {
3 ArgIterator iterator = new ArgIterator(__arglist);
4 return iterator.GetRemainingCount();
5 }
如果我使用下面代碼調用該函數
將被返回5給變量x。這是因爲我們給這個方法傳遞了5個參數。我們可以訪問每個參數,如:
2 TypedReference.ToObject(tf)
每次調用GetNextArg,GetRemainingCount將減1,直到遍歷完迭代器的每個對象。
2、__refvalue
另一個有趣的關鍵字是__refvalue。它是用來獲取一個引用對象的的值。你可以用來從TypedReference對象中獲得實際對象。這需要兩個參數,第一個就是TypedReference對象和另一個是轉換的類型。看看下面代碼:
3、__makeref
__makeref將使從對象中找出TypedReference對象。這跟_refvalue剛剛相反。請看下面的代碼:
2 TypedReference tf = __makeref(name);
4、 __reftype
__reftype是用來從TypedReference類型的對象獲得類型。看下面代碼所示:
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語句返回。
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語句在個固定的內存地址設置一個指針,它不會被移動到任何地方,即使執行了垃圾收集線程。讓我們來看看下面的代碼:
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異常。
看下這段代碼:
2 int y = int.MaxValue;
3 int z = checked(x + y);
上述聲明中,當執行到x + y時,將拋出OverflowException異常。 checked用來檢查運算溢出並引發相應的異常。 當發生OverflowException異常時,z被賦值爲0。
當我們不需要拋出異常時,我們可以使用關鍵字unchecked。
2 int y = int.MaxValue;
3 int z = unchecked(x + y);
通過執行上面的代碼,z的值將被賦值爲-2。
8、Volatile
volatile關鍵字用於定義一個變量,這個變量跨多個線程修改而不被lock(雖然我們大部分的時間鎖定它們)。 volatile變量不受編譯器優化,因此我們將獲得該變量的所有的時間最新的值。見下面的例子:
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用於快速獲取內存。當我們使用堆棧,我們可以利用內存快速存取的優勢。我們可以這樣聲明一個數組:
注意:您應該始終牢記,stackalloc內存是非常有限的。它是由每個線程默認爲1MB。因此,如果我們需要大量的內存(超過1MB),我們必須回到原來堆內存結構。
10、 Global ::
當想要用本地的命名空間隱藏的全局的命名空間,這個關鍵字是非常方便的。假設我們有我們的項目中創建了一個名爲System的類,C#中是允許這樣做的。當我想使用全局的System空間時,我們必須使用global::.。讓我們來看看下面的例子:
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別名:
當你想縮短比較長的命名空間時,可以使用命名空間的別名。
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的對象,直接訪問靜態函數。
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
現在參考我們的使用
2 extern alias XV2;
13、??
??與null值一起使用。在2.0中引入。看以下內容:
2 x = x ?? new MyClass();
??的意思是說,如果X是null 值,將new MyClass() ,否則將賦值現有的X值
14、@variables
通常是C#不允許使用關鍵字做變量的。但是有一種方式例外。我們可以通過使用@創建與關鍵字具有相同的名稱的變量。
假設我們定義:
這意味着聲明瞭一個名字爲int的變量和並分配10給它。
15、Readonly
目前,readonly是C#關鍵字,用來創建不能被程序修改的變量。該聲明爲readonly的變量,變量的值將被分配一次,它將在整個對象執行過程中保持相同的值。
聲明一個只讀變量:
聲明瞭一個值爲20 的變量。再對這個變量賦值是不允許的。
16 、Const & readonly 的區別?
readonly類似關鍵字const。唯一不同的是, const 變量在編譯時定義的,readonly變量在運行時定義。您可以從內部構造函數中分配readonly變量的值,因此根據你的構造函數分配,readonly值可能不同。
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非常容易獲取對象默認的分配的值。
2 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:
這裏nullableint將被賦值null。
如果您訪問nullable變量,您將獲得2個屬性。
HasValue屬性將返回false,如果null被分配給變量;
Value屬性返回變量的實際值。
您還可以使用每種nullable類型的對象的GetValueOrDefault函數來得到變量的默認值。
結論:
我的目的是給你一個簡短方式介紹一下這些關鍵字的知識,以及如何去使用它們。請隨意發表您的評論。
PS:
1到4是Undocumented關鍵字,5到18是documented關鍵字。
如果覺得對你有點幫助,或者有點意思。請推薦一下,謝謝。
參考文章:UnCommon C# keywords - A Look