1. 程式人生 > 實用技巧 >重學c#系列——索引器(九)

重學c#系列——索引器(九)

前言

對於索引器,我們肯定不會陌生。為什麼會有索引器這個東西呢?我們發現這東西很像是屬性,只是通過索引方式去呼叫,那就慢慢揭開他的面紗吧。

正文

假設我們要對外暴露一個數組,為了體現其封裝性,我們使用陣列。

public Class Instance{
public int[] IntArr{get;set;}
}

這樣似乎就可以了,但是有個問題,那就是假如我要取得是其中的一個值。

那麼可以這樣寫instance.IntArr[0],這樣寫似乎沒得啥子問題呢,但是執行過程是instance.IntArr 會建立一個匿名物件,然後再取其中的索引0。

這樣似乎是不必要的。

然後索引器可以這樣:

public Class Instance{
private int[] intArr;
public int this[int index]
{
   get { return intArr[index]; }
   set { intArr[i]=value; }
}
}

那麼呼叫方式是這樣的:instance[i]。

這種方式比較簡單,很多情況下都是不希望知道內部怎麼實現的,比如說索引是一個string,傳遞的值需要經過某種計算然後得出。

比如說官網給出一個例子:

using System;
// Using a string as an indexer value
class DayCollection
{
    string[] days = { "Sun", "Mon", "Tues", "Wed", "Thurs", "Fri", "Sat" };

    // Indexer with only a get accessor with the expression-bodied definition:
    public int this[string day] => FindDayIndex(day);

    private int FindDayIndex(string day)
    {
        for (int j = 0; j < days.Length; j++)
        {
            if (days[j] == day)
            {
                return j;
            }
        }

        throw new ArgumentOutOfRangeException(
            nameof(day),
            $"Day {day} is not supported.\nDay input must be in the form \"Sun\", \"Mon\", etc");
    }
}

通過這種模式實現一個類陣列的結構,會使我們的程式碼簡潔很多。

索引還是和屬性用法還是不同的,索引只能是例項成員。我也不知道為什麼要這樣設計,但是我是這樣想得,加上其不是一個例項成員,而是一個靜態成員,似乎是沒有任何意義的,因為我沒

有找到任何這樣的意義。

值得注意的是,介面中依然存在索引。

官網給出的例子是:

// Indexer on an interface:
public interface IIndexInterface
{
    // Indexer declaration:
    int this[int index]
    {
        get;
        set;
    }
}

// Implementing the interface.
class IndexerClass : IIndexInterface
{
    private int[] arr = new int[100];
    public int this[int index]   // indexer declaration
    {
        // The arr object will throw IndexOutOfRange exception.
        get => arr[index];
        set => arr[index] = value;
    }
}

和介面定義的規則一樣,在介面中我們不能去做具體的試下,只需定義即可。

因為介面可以繼承,那麼可能會形成屬性衝突,那麼具體實現的時候就需要:

public int IIndexInterface.this[int index]   // indexer declaration
{
     // The arr object will throw IndexOutOfRange exception.
     get => arr[index];
     set => arr[index] = value;
}

系列持續更新中。