一、this關鍵字
在C#中,this關鍵字有以下3種常見的用法:
1.用在類的屬性、實例方法或實例構造方法中,區分成員名和本地變量(或參數)。下面的示例聲明一個名為Myclass的類,類中包括一個實例字段myVal和一個實例構造函數,該構造函數帶一個名為myVal的參數,在方法中,通過this可以在語義上區分成員名myVal和參數名myVal。(注意:在實際編程中是不建議參數名和字段名相同的,這樣做降低了代碼的易讀性,這里只是為了說明this關鍵字的用法而已)。
1 class MyClass 2 { 3 // 聲明一個名為"myVal"的整型字段 4 public int myVal = 10; 5 6 // 聲明一個構造函數,該函數帶一個名為"myVal"的參數 7 public MyClass(int myVal) 8 { 9 // "this"表示MyClass類的當前實例 10 // 在這里通過this可以在語義上區分成員名myVal和參數名myVal 11 this.myVal += myVal; 12 } 13 }
2.this表示的是當前對象,可以把它作為實參傳遞到其它方法。例如下面聲明一個類MyClass1,它包括一個實例成員方法Compute,而Compute帶一個類型為MyClass的參數,該參數在方法中參加運算。
1 class MyClass1 2 { 3 // 聲明一個計算的方法,參數類型為MyClass 4 public static int Compute(MyClass mc) 5 { 6 int resutl = 0; 7 if (mc != null) 8 { 9 resutl += mc.myVal; 10 } 11 return resutl; 12 } 13 }
下面在類MyClass的構造方法中添加了一個本地變量的聲明,該變量初始化的值來自MyClass1的Compute方法的計算結果。而這時就可以將this作為實參傳遞給調用方法了:
1 class MyClass 2 { 3 // 聲明一個名為"myVal"的整型字段 4 public int myVal = 10; 5 6 // 聲明一個構造函數,該函數帶一個名為"myVal"的參數 7 public MyClass(int myVal) 8 { 9 // "this"表示MyClass類的當前實例 10 // 在這里通過this可以在語義上區分成員名myVal和參數名myVal 11 this.myVal += myVal; 12 13 // 使用this作為當前對象的實參傳遞給Compute方法 14 int res = myVal + MyClass1.Compute(this); 15 } 16 }
3.聲明索引器。接下來在第二部分當中分析索引器的聲明和使用方法。
此外,應當注意的一點:由於靜態成員函數存在於類一級,並且不是對象的一部分,沒有 this 指針,因此不能在靜態方法中使用this關鍵字。在靜態方法中引用 this 是錯誤的。
二、索引器
1.通過點運算符訪問實例成員
一般情況下,我們是通過點運算符(“實例名.成員名”)的方式來訪問類的實例成員的。比如下面的示例,該例中其實是通過調用屬性的set訪問器為成員字段賦值,並且通過get訪問器讀取成員字段的值的。

1 class Course 2 { 3 public float Chinese { set; get; } 4 public float Math { set; get; } 5 public float Englisth { set; get; } 6 } 7 8 class Program 9 { 10 static void Main(string[] args) 11 { 12 // 聲明一個Course類的實例 13 var course = new Course(); 14 15 // 使用傳統的“實例名.成員名”方式訪問成員 16 // 賦值 17 course.Chinese = 95; 18 course.Math = 100; 19 course.Englisth = 80; 20 // 取值 21 Console.WriteLine("語文:{0},數學:{1},英語:{2}", course.Chinese, course.Math, course.Englisth); 22 Console.ReadKey(); 23 } 24 }
2.通過索引器訪問實例成員
通過觀察上面示例的代碼,可以發現:該類的所有成員具有相同的類型float,它們其實可以像訪問數組一樣的方式訪問,所以,我們可以為類提供另一種實例成員訪問方式:索引器。下面的代碼為上面的Course類聲明加上了一個float類型的索引,並在Main方法中通過索引存取數據:

1 class Course 2 { 3 public float Chinese { set; get; } 4 public float Math { set; get; } 5 public float Englisth { set; get; } 6 7 // 聲明一個公開的float類型的索引器 8 public float this[int index] 9 { 10 // set訪問器:賦值 11 set 12 { 13 switch (index) 14 { 15 case 0: 16 this.Chinese = value; 17 break; 18 case 1: 19 this.Math = value; 20 break; 21 case 2: 22 this.Englisth = value; 23 break; 24 default: 25 // 索引越界時拋出異常 26 throw new ArgumentOutOfRangeException(); 27 } 28 } 29 // get訪問器:取值 30 get 31 { 32 switch (index) 33 { 34 case 0: 35 return this.Chinese; 36 case 1: 37 return this.Math; 38 case 2: 39 return this.Englisth; 40 default: 41 throw new ArgumentOutOfRangeException(); 42 } 43 } 44 } 45 } 46 47 class Program 48 { 49 static void Main(string[] args) 50 { 51 // 聲明一個Course類的實例 52 var course = new Course(); 53 54 // 使用索引器訪問實例成員 55 // 賦值 56 course[0] = 95; 57 course[1] = 100; 58 course[2] = 80; 59 // 取值 60 Console.WriteLine("語文:{0},數學:{1},英語:{2}", course[0], course[1], course[2]); 61 Console.ReadKey(); 62 } 63 }
3.什么是索引?
上面已經聲明並且使用了索引,這里分析總結索引的概念和特征:
1).索引的概念
索引也是一種類成員,而且必須為實例成員,因為它就是為實例成員提供的一種訪問方式,所以不能聲明為static的。索引與屬性類似,也有get訪問器和set訪問器。而且索引實際上就是一組get訪問器和set訪問器,而訪問器的本質是方法,所以說,索引器的本質就是方法。索引器經常是在主要用於封裝內部集合或數組的類型中聲明的。
2).索引聲明
索引聲明使用下面的語法:
[訪問修飾符] 返回值類型 this [ 參數1,參數2...]
{
get{......}
set{......}
}
語法要點:索引名稱永遠為this;索引的參數在方括號中間;索引的參數列表中至少有一個參數。
3).set訪問器
當索引被用於賦值時,它的set訪問器被隱式調用, set訪問器的特征如下:
第一,它的返回值類型為void。
第二,它的參數列表和索引中聲明的參數列表的相同。
第三,它有一個名為value的隱式值參數,參數類型和索引的類型相同。
4).get訪問器
當索引被用於取值時,get訪問器被隱式調用,get訪問器的特征如下:
第一,它的返回值類型與索引類型相同。
第二,它的參數列表和索引中聲明的參數列表的相同。
5).索引的安全性
在客戶端代通過索引訪問成員時,很可能發生索引越界等一些異常情況。有兩種方式提高索引的安全性:
第一,為索引聲明嚴格的訪問級別控制,比如可以將set訪問器的修飾符改為private。

1 // set訪問器:賦值 2 private set 3 { 4 switch (index) 5 { 6 case 0: 7 this.Chinese = value; 8 break; 9 case 1: 10 this.Math = value; 11 break; 12 case 2: 13 this.Englisth = value; 14 break; 15 default: 16 // 索引越界時拋出異常 17 throw new ArgumentOutOfRangeException(); 18 } 19 }
第二,檢查成員的個數,或拋出異常。
1 // 索引越界時拋出異常 2 throw new ArgumentOutOfRangeException();
6).索引重載
索引可以聲明多個參數,也可以重載,索引重載只要參數列表不同就行了。下面為Course類聲明幾個索引的重載。

1 class Course 2 { 3 public float Chinese { set; get; } 4 public float Math { set; get; } 5 public float Englisth { set; get; } 6 7 // 聲明一個公開的float類型的索引器 8 public float this[int index] 9 { 10 // set訪問器:賦值 11 set 12 { 13 switch (index) 14 { 15 case 0: 16 this.Chinese = value; 17 break; 18 case 1: 19 this.Math = value; 20 break; 21 case 2: 22 this.Englisth = value; 23 break; 24 default: 25 // 索引越界時拋出異常 26 throw new ArgumentOutOfRangeException(); 27 } 28 } 29 // get訪問器:取值 30 get 31 { 32 switch (index) 33 { 34 case 0: 35 return this.Chinese; 36 case 1: 37 return this.Math; 38 case 2: 39 return this.Englisth; 40 default: 41 throw new ArgumentOutOfRangeException(); 42 } 43 } 44 } 45 46 // 索引重載 47 public float this[string name, float val] 48 { 49 set 50 { 51 switch (name) 52 { 53 case "Chinese": 54 this.Chinese = value + val; 55 break; 56 case "Math": 57 this.Math = value + val; 58 break; 59 case "English": 60 this.Englisth = value + val; 61 break; 62 default: 63 throw new ArgumentOutOfRangeException(); 64 } 65 } 66 get 67 { 68 switch (name) 69 { 70 case "Chinese": 71 return this.Chinese; 72 case "Math": 73 return this.Math; 74 case "English": 75 return this.Englisth; 76 default: 77 throw new ArgumentOutOfRangeException(); 78 } 79 } 80 } 81 82 // 重載2:只讀索引 83 protected string this[int index, string name, bool flag] 84 { 85 set 86 { 87 88 } 89 } 90 91 }
三、索引器和屬性的比較
1.相同點
1).索引和屬性都不用分配內存位置來存儲。
2).索引和屬性都是為類的其它成員提供訪問控制的。
3).索引和屬性都有get訪問器和set訪問器,它們可以同時聲明兩個訪問器,也可以只聲明其中一個。
2.不同點
1).屬性通常表示單獨的數據成員,而索引表示多個數據成員。
2).屬性既可以聲明為實例屬性,也可以聲明為靜態屬性,而索引不能聲明為靜態的。
3).屬性有簡潔的自動實現屬性,而索引必須聲明完整。
4).get訪問器:屬性的 get 訪問器沒有參數,索引器的 get 訪問器具有與索引器相同的形參表。
5).set訪問器:屬性的 set 訪問器包含隱式 value 參數。除了值參數外,索引器的 set 訪問器還具有與索引器相同的形參表。
參考:http://msdn.microsoft.com/zh-cn/library/6x16t2tx(VS.100).aspx