2

次のシナリオがあるとします: Dictionary から派生したクラスで、このクラスにも文字列インデクサーの実装がありますが、インデクサーが値を返すプロパティはキーではありません (要素の辞書のように考えてください。キーとしての int または guid だけでなく、インデクサーを作成したい文字列プロパティもあります)。

public class StringDictionary<TKey> :
    Dictionary<TKey, object>
{
    public object this[string val]
    { get { } set { } }
}

次に、StringDictionary をインスタンス化するときの TKey の型に応じて、C# がどのように動作するか (かなり直感的です) を次に示します。

StringDictionary<string> dict1;
dict1["string"]; // will use the indexer defined in StringDictionary

StringDictionary<int> dict2;
dict2[0]; // will use the indexer defined in Dictionary
dict2["string"]; // will use the indexer defined in StringDictionary
  • TKey が文字列の場合、StringDictionary で宣言されたインデクサーのみが使用可能になります
  • TKey が文字列以外の場合、両方のインデクサーを使用できます (StringDictionary の文字列インデクサーと Dictionary の TKey インデクサー)。

私の質問は、上記の例のように、ジェネリック基本クラスで定義されたインデクサーと派生クラスで定義されたインデクサーの間に「競合」がある場合、C# はどのインデクサーを使用するかをどのように決定するのでしょうか? TKey が文字列として明示的に宣言され、新しいインデクサーが継承されたものを単に非表示にするのと同じですか?

私が言ったように、それは非常に直感的で、エラーや警告をスローしませんが、これが機能するメカニズムを知りたいです.

4

1 に答える 1

3

シャドーイング

この基本クラスがあるとします

public class BaseClass
{
    public string Name { get; set; }
}

ここで、それから派生し、何らかの理由で異なる動作をする name プロパティが必要であるとします。

public class DerivedClass
{
    public string Name
    {
        get { return "Always the same"; }
        set { throw new Exception(); }
    }
}

C# コンパイラは、これを行うことができないと文句を言うでしょう。クラスには既にNameプロパティがあります! できることは、C# コンパイラに、プロパティを使用するときにそのプロパティDerivedClassを使用するように指示することですName。これを行うには、newプロパティを のNameプロパティに追加しDerivedClassます。

public new string Name

これをシャドーイングといいます

副作用

DerivedClassすべてのタイプとして使用すると、DerivedClass期待どおりに動作します。

DerivedClass derived = new DerivedClass();
derived.Name = "Joe";   // Exception

ただしName、基本クラスを使用して使用しようとすると、実際にはBaseClass実装を使用しています。

BaseClass base = derived;
base.Name = "Joe";      // No Exception

これを防ぐ方法はありません。

質問に戻る

newジェネリックを使用する場合、インデクサーは常にnewメソッドであるとは限らないため (TKey が である場合のみ) 、インデクサーを としてマークしませんstringが、そうする必要がある場合は暗黙的にnewです。したがって、そのような場合、C# コンパイラは、認識しているメソッド/インデクサーのバージョンを使用します。

として使用する場合StringDictionary<string>、カスタム実装が使用されます。として使用する場合は、インデクサーDictionary<string, string>の実装を使用します。Dictionary<string,string>

于 2013-06-09T18:03:03.163 に答える