C#基礎 [13] this關鍵字和索引器


一、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訪問器讀取成員字段的值的。

View Code
 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方法中通過索引存取數據:

View Code
 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。

View Code
 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類聲明幾個索引的重載。

View Code
 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   

      


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM