2011-01-13 2 views
0

私は現在IDictionary <を拡張しているインターフェイス(および拡張辞書<>)を持っていますが、このインターフェイスの実装ではエントリを追加または削除できません(既存のエントリを許可したいしかし変更する)。私は単にReadOnlyCollectionのアプローチを取ってNotSupportedExceptionをスローすることができますが、これは少し間違っていると感じます。メソッドを隠して、別のインタフェースの背後にあるメソッドの実装方法が違うのは悪い考えですか?

代わりに私はインターフェイスを壊したいので、アクセサービット用とミューテータビット用の2つがありました。

public interface IAccessor<TKey, TValue> 
    { 
    TValue this [TKey key] { get; set; } 
    } 

、その後、私の元のインターフェースになった:

public interface IAttributeDictionary<TKey, TValue> : IDictionary<TKey, TValue>, IAccessor<TKey, TValue> 
    { 
    new TValue this [TKey key] { get; set; } 
    } 

そして、実装クラスこれは、私がこのような何かを(簡潔にするため削除ほとんどのメソッドを)終わったこれを実行することを除いて、すべてokです私はIDictionaryIAccessorにインデクサーの間であいまいさを避けるために、インデクサ新をしなければならなかった

public class AttributeDictionary<TKey,TValue>: Dictionary<TKey, TValue>, IAttributeDictionary<TKey, TValue> 

:として定義されます。実際の問題は、Dictionaryのセッターインデクサーの動作が辞書に新しいエントリを作成することです。 IAccessorインターフェイスでエントリの変更のみを許可し、作成しないようにするには、AttributeDictionaryの実装で何をすべきですか? IAccessorインデクサメソッドを明示的に実装する必要があります。これは、指定されたキーが辞書にあるかどうかを最初にチェックし、そうでない場合は例外をスローします。または、IAccessorインターフェイスでインデクサーを捨て、代わりにGetValueSetValueのメソッドを使用し、混乱を避ける必要がありますか?

答えて

1

IDictionaryをまだ実装しようとしているというのは問題だと思うのですが、私はそのインターフェイスをAttributeDictionaryに実装すべきではないと思っています。 。しかし、AttributeDictionaryのインスタンスをIDictionaryとするメソッドに送信する必要があるため、サポートする必要がある場合は、使用可能なIDictionaryの実装チェーンで上位のインターフェイスがないので、次善策は単に実装することですIDictionary単独でインデクサーのセッターに投げ込んでください。

あなたが間違ったインデクサーと呼んでいる行を細かいバグに陥らせているような気がします。特に、インターフェイス自体を介してクラスのインスタンスを扱うときは、本当にわかりません。

EDIT:

何このようなアプローチについて:

public interface IAccessor<K,V> { 
    V this[K key] { get; } 
} 

public interface IAttributeDictionary<K,V> : IAccessor<K,V>, IDictionary<K,V> { 
    // This interface just composes the other two. 
} 

public class Test<K,V> : IAttributeDictionary<K,V> { 
    // This will implement the indexer for both IAccessor and IDictionary. 
    // But when the object is accessed as an IAccessor the setter is not available. 
    public V this[K key] { 
     get { Console.WriteLine("getter"); return default(V); } 
     set { Console.WriteLine("setter"); } 
    } 

    // ...the rest of IDictionary goes here... 
} 

class Program { 
    static void Main (string[] args) { 
     // Note that test can be accessed as any of the appropriate types, 
     // and the same getter is called. 
     Test<string,int> test = new Test<string, int>(); 
     int a = test["a"]; 
     int b = ((IDictionary<string, int>)test)["b"]; 
     int c = ((IAccessor<string, int>)test)["c"]; 
    } 
} 

EDIT 2.0:この回答へのサムの最初のコメントの後 以下のコメント内のすべての議論の後、私はついにかもしれないと思いますその問題を理解してください...

私は、(私の意見では)あなたが望む振る舞いは、非常に珍しい予期しないものであるので、インデクサーを使用すべきではないと主張します。代わりにGetValueForKeyChangeValueForKeyIAccessorに設定し、具体的な実装クラスでIDictionaryのインデクサを実装することができます。何らかの理由でそれが受け入れられない場合は、明示的なインターフェイス実装を使用してIAccessorと実装クラスのインデクサを実装することをお勧めします。どちらの場合も、IAttributeDictionaryの新しい宣言は必要ありません。

+0

ありがとうございました。たぶん私の質問から明らかではなかったが、私はAttributeDictionaryのセッターに新しい値を追加できるようにしたい。私は、IAccessorインターフェイスのセッターを介して新しい値を追加することを拒否したいだけです(それはそのように文書化されます)。他のクラスでは、IAccessorインターフェイスだけを実装するので、最初にこの分割を行いたいのです。私たちは、IAccessorインターフェイスの実装だけを必要とする新しい属性を追加する必要はありませんが、(AttributeDictionaryのように)変更可能なオブジェクトを渡すことができます... ctd –

+0

またはできないオブジェクト(つまり、IAccessor自体しか実装していないもの) –

+0

ああ、うーん。私はあなたの質問を間違えたと思う。なぜIAccessorにはsetメソッドがありますか?なぜそれをゲット専用にしないのですか?私はそれが問題を単純化できると思う。 –

関連する問題