1. 程式人生 > >C#中的索引器(Indexers)

C#中的索引器(Indexers)

 

前兩天剛剛學習完了屬性,這兩天又摟完了索引器,發現兩者非常的相似,但是相似之外還有一些不同之處。今天就來總結一下索引器--Indexers

索引器的作用及格式

索引器的作用就是能夠使類或者結構體的例項物件像陣列一樣使用下標的方式訪問集合物件。索引器的書寫格式和屬性非常的類似,像是一個帶有引數的屬性,但是屬性名只能使用this關鍵字,並且指定了索引型別,下面看一個簡單的例子:

  class MyClass{
     int[] numInts = new int[10];//定義一個數組
     public int this[int index]{
         get
        {
             return numInts[index];
        }
         set
        {
             numInts[index] = value;
        }
    }
}
 
 class Program
{
static void Main(string[] args)
{
MyClass myClass = new myClass();
myClass[0] = 1;
myClass[1] = 2;
int num = myClass[1];
}
}

在這個例子中,myClass通過get訪問器獲取numInts中的值,通過set訪問器將值傳遞給value進行賦值,這是最簡單的操作。但其實在get和set訪問器中還可以進行一些條件的判斷,比如在get訪問器中判斷下標是否越界;在set訪問器中判斷傳值是否超出限定範圍等等,能做的操作太多了。

只讀&只寫索引器的實現

上面說過,索引器與屬性非常的相似都具有一對訪問器,只是訪問器接收的引數有所不同。既然擁有類似的訪問器,那麼只讀或者只寫功能的索引器與只讀或者只寫功能的屬性,也是差不多的,下面具體闡述一下。 在之前的屬性文章的說到過屬性的只讀或者只寫有兩種實現方式:

  1. 隱藏getter或者setter

  2. 給getter或者setter新增private訪問修飾符 這裡同樣適用於索引器,只不過有以下幾點需要注意:

  3. 通過隱藏getter來實現只讀索引器的方式,只能在類中實現,結構體中的索引器不能隱藏getter

  4. 通過給getter新增private訪問修飾符實現只讀索引器也只能在類中實現,結構體中getter必須能被外界訪問到

  5. 使用新增private訪問修飾符的方式來是實現只讀或者只寫索引器時,getter和setter必須同時存在,缺一不可。 下面使用兩種方式分別實現只讀索引器:

class MyClass
{
private int[] nums = new []{1, 2, 3, 4, 5, 6, 7};

public int this[int index]//通過新增private實現只寫索引器
{
get{
               return this.nums[index];
}
private set { this.nums[index] = value; }
}
}

class MyClass
{
private int[] nums = new []{1, 2, 3, 4, 5, 6, 7};

public int this[int index]//通過隱藏setter實現只讀索引器
{
get{
               return this.nums[index];
}
}
}

索引器在介面中的使用

介面中能夠宣告的型別只有四種,其中就包含索引器。在介面中,索引器的使用也和屬性大抵相似,getter和setter同樣沒有方法體,只用";"結尾。也可以通過隱藏getter或者setter來定義只讀或者只寫索引器,具體在介面中的使用如下:

  interface ITestFace
{
int this[int index] { get; set; }
}

同屬性一樣,派生類在實現索引器的時候也有兩種選擇:

  1. 可以為索引器新增virtual關鍵字,使後續的派生類能夠進行重寫

class Test2:ITestFace
{
private int[] count = new[] {1, 2, 3, 4};
public virtual int this[int index]
{
get => count[index];
set => count[index] = value;
}
}

class Test1:Test2
{
private int[] count = new[] {0,0,0,0 };
public override int this[int index]
{
get
{
return this.count[index];
}
}
}
class Program
{
static void Main(string[] args)
{
Test2 Test1 = new Test1();
Console.WriteLine(Test1[1]);
}
}
0
請按任意鍵繼續. . .
  1. 直接在索引器前新增介面名稱,刪除訪問修飾符,進行顯示介面實現

class Test2:ITestFace
{
private int[] count = new[] {1, 2, 3, 4};
int ITestFace.this[int index]
{
get => count[index];
set => count[index] = value;
}
}
class Program
{
static void Main(string[] args)
{
ITestFace tf = new Test2();
Console.WriteLine(tf[1]);
}
}
2
請按任意鍵繼續. . .

使用顯示介面實現的形式,索引器不屬於派生類所有,只能被對應介面型別的派生類例項物件所使用。

索引器的其他使用方式

以上用到的索引器都是隻包含一個索引值,但其實索引器的所引致可以包含多個,根據自己的需求來使用,這裡就不過多介紹了,需要的可以自行Google或者百度。下面介紹一下如何在索引器中使用表示式主體定義。 表示式主體定義和lambda表示式很像,概念什麼的這裡就略去了,直接進入主題,在C#6當中,如果索引器只讀,且get訪問器只有一條語句,那麼就可以使用表示式主體定義的方式進行書寫,更加簡潔:

  
 class MyClass2
{
private int[] nums = new []{1, 2, 3, 4, 5, 6, 7};

public int this[int index] => this.nums[index];
}

這種方式只適用於只讀索引器,但是在C#7當中,還有另外一種使用表示式主體定義的方式,來簡便的書寫索引器,如下所示:

  class MyClass3
{
private int[] nums = new []{1, 2, 3, 4, 5, 6, 7};

public int this[int index] {
           get=>this.nums[index];
           set=> nums[index] = value;
}
}

以上,就是關於索引器的一些內容,不足之處還請指教,下面列出一些使用索引器的注意事項,供大家使用時參考:

  1. 通過索引器傳遞進來的值會傳遞給value變數,value的型別必須與索引器的型別相同

  2. 索引器不能作為ref或者out引數使用,陣列可以

  3. 索引器只屬於物件,不能使用static進行修飾

  4. 結構體中也可以使用屬性,但是使用時結構體需要使用關鍵字new進行初始化,因為索引器只屬於物件

  5. 索引器和屬性很相似,屬於有參的屬性,使類或者結構體可以訪問像陣列一下訪問資料

  6. 使用索引器獲取資料或者修改資料,接收或者傳遞的值的型別必須與索引器的型別相同

  7. 索引器和屬性相同,也可以通過隱藏get或者set訪問器來實現只讀索引器或者只寫索引器,但是在結構體中必須保留get訪問器,類中可以選擇性的隱藏

  8. 索引器的只讀或者只寫也可以通過給get或者set訪問器新增合適的訪問修飾符private來實現,但是在結構體中get訪問器不能設為私有的或者被保護的,只能為public型別的

PS:以上均是自己學習之後理解所寫,水平有限難免會出現錯誤之處,總是唯恐給閱讀到小夥伴造成誤導,所以希望能夠以質疑的態度去瀏覽,也希望小夥伴能夠批評指出,共同成長。