18個不常見的C#關鍵字,您使用過幾個?

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[] { 123 };
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 ?? 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關鍵字分配。
因此,如果我們寫:

1 int x = default(int);//will be assigned to 0

類似於:
int x;
一般情況下,當類型不確定時,我們可以使用default來分配特定的值給對象。讓我們看看該示例:

1 public T GetDefault<T>()
2 {
3      return default(T);
4 

該函數返回每個類型的默認值。從而

因此,我們可以使用關鍵字default非常容易獲取對象默認的分配的值。

1 int defx = this.GetDefault<int>(); //will assign 0
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:

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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章