12

このコードを持っている...

var b = new ReadOnlyCollection<int>(new[] { 2, 4, 2, 2 });
b[2] = 3;

2 行目でコンパイル エラーが発生します。ReadOnlyCollection<T>実装IList<T>とインターフェイスthis[T]にセッターがあるため、実行時エラーが発生することが予想されIList<T>ます。

ReadOnlyCollection の機能を複製しようとしましたが、セッターを削除するthis[T]とコンパイル エラーが発生します。

4

3 に答える 3

17

インデクサーは明示的なインターフェイスの実装で実装されているため、次の場合にのみアクセスできます。

IList<int> b = new ReadOnlyCollection<int>(new[] { 2, 4, 2, 2 });
b[2] = 3;

また

var b = new ReadOnlyCollection<int>(new[] { 2, 4, 2, 2 });
((IList<int>)b)[2] = 3;

もちろん、実行時に失敗します...

これは完全に意図的なものであり、役に立ちます。これは、コンパイラReadOnlyCollection.

ただし、プロパティ/インデクサーの半分を暗黙的に実装し、半分を明示的に実装するという、興味深い比較的珍しい手順です。

以前の考えに反して、ReadOnlyCollection<T> 実際にはインデクサー全体を明示的に実装しているだけでなく、読み取り専用のパブリック インデクサーも提供していると思います。つまり、次のようなものです。

T IList<T>.this[int index]
{
    // Delegate interface implementation to "normal" implementation
    get { return this[index]; }
    set { throw new NotSupportedException("Collection is read-only."); }
}

public T this[int index]
{
    get { return ...; }
}
于 2009-09-11T09:15:58.060 に答える
2

これは IList.Items を明示的に実装するため、非公開になり、その実装に到達するにはインターフェイスにキャストする必要があり、代わりに使用される新しい this[...] インデクサーを実装します。アクセサーを取得します。

コレクションを IList にキャストすると、コードはコンパイルされますが、代わりに実行時に失敗します。

残念ながら、C# でインデクサーを作成するにはキーワードを使用する必要があるため、C# でこれを行う方法がわかりません。次のようにthis書くことはできません。

T IList<T>.this[int index] { get; set; }
于 2009-09-11T09:15:48.213 に答える
1

魔法はありません。ReadOnlyCollection独自のインデクサーとIList<T>インターフェイスを実装するインデクサーの実装が異なるだけです。

public T Item[int index] { get; }

T IList<T>.Item[int index] { get; set; }

リストを にキャストするIList<int>と、コンパイル エラーの代わりに実行時エラーが発生します。

((IList<int>)b)[2] = 3;

編集:
独自のクラスにインデクサーを実装するには、次のthisキーワードを使用します。

public T this[int index] { get { ... } }

T IList<T>.this[int index] { get { ... } set { ... } }
于 2009-09-11T09:17:53.077 に答える