0

我有一个当前扩展 IDictionary<> 的接口(以及一个扩展 Dictionary<> 的实现),但我想要一个不允许添加或删除条目的接口的实现(我想允许现有的条目虽然改变了)。我可以采用 ReadOnlyCollection 方法并抛出 NotSupportedException,但这感觉有点不对劲。

相反,我想分解接口,所以我有一个用于访问器位,一个用于更改器位。这一切都很好,只是为了做到这一点,我最终得到了这样的结果(为简洁起见,大多数方法都被删除了):

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; }
    }

一个实现类定义为:

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

我必须使索引器成为新的,以避免 和 中的索引器之间出现IDictionary歧义IAccessor。但真正的问题是设置器索引器在 a 上的行为是Dictionary在字典中创建一个新条目。因为我希望IAccessor界面只允许修改条目而不是创建条目,我应该在实现中做什么AttributeDictionary?我是否应该明确实现IAccessor索引器方法,该方法首先检查给定键是否在字典中,如果没有则抛出异常,或者拥有 2 个具有不同行为的索引器是个坏主意?或者我应该放弃IAccessor界面中的索引器而只使用GetValueandSetValue方法并避免混淆?

4

1 回答 1

1

令我印象深刻的问题是您仍在尝试实现IDictionary-我认为您不应该在您的接口上实现该接口AttributeDictionary(因为您并不真正支持该接口要求的全部功能)。但是,如果您必须支持它,因为您需要将实例发送AttributeDictionary到采取的方法IDictionary并且在您可以使用的实现链中没有更高的接口IDictionary,我认为下一个最好的事情是简单地IDictionary单独实现并投入索引器的设置器。

我觉得您现在尝试的方法只会导致微妙的错误,您在不知道它的情况下调用错误的索引器,特别是在通过接口本身处理类的实例时。

编辑:在山姆对这个答案的第一次评论之后:

像这样的方法怎么样:

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"];
    }
}

编辑 2.0:在下面评论中的所有讨论之后,我想我可能最终理解了这个问题,所以......

我认为IAccessor真的不应该使用索引器,因为(在我看来)你想要的行为是非常不寻常和出乎意料的。相反,我将拥有GetValueForKey并且可以提供您想要的行为,并从具体实现类中实现索引器。如果出于任何原因这是不可接受的,我建议使用显式接口实现来实现实现类中的实现及其索引器——在这两种情况下,我认为新的声明是不必要的。ChangeValueForKeyIAccessorIDictionaryIAccessorIAttributeDictionary

于 2011-01-13T16:54:24.423 回答