C# - 需要一个允许空键的IDictionary实现

Cly*_*yde 13 c# collections idictionary

基本上,我想要这样的东西:

Dictionary<object, string> dict = new Dictionary<object, string>();
dict.Add(null, "Nothing");
dict.Add(1, "One");
Run Code Online (Sandbox Code Playgroud)

是否有任何内置到基类库中允许这样做?添加null键时,前面的代码将在运行时抛出异常.

谢谢

LBu*_*kin 11

您可以避免使用null并创建一个执行相同操作的特殊单例值类.例如:

public sealed class Nothing
{ 
  public static readonly Nothing Value = new Nothing(); 
  private Nothing() {}
}

Dictionary<object, string> dict = new Dictionary<object, string>();
dict.add(Nothing.Value, "Nothing");
dict.add(1, "One");
Run Code Online (Sandbox Code Playgroud)

如果您打算使您的集合更强类型,这种方法将无法工作 - 例如,您希望密钥是一个字符串.由于字符串是密封的,因此您无法继承它以创建"特殊值"替代null.你的选择变得有点复杂.你可以:

  1. 创建一些特殊的常量值来表示"空"/"空"的情况.有点hacky,绝对是混乱的途径.如果字典对于某些实现类是完全私有的,并且您可以编写一些Encode/Decode实用程序方法以避免传播有关如何在整个位置翻译键的知识,这可能是一种可行的方法.
  2. 创建自己的IDictionary实现,内部委托给Dictionary <>实例 - 除了null的情况.这违反了对IDictionary <>接口的记录期望,它确实说明了null键应该抛出异常.但是,如果这是解决您真正问题的唯一方法,那么您可以逃脱它.这仅在您拥有并创建字典实例时才有效.
  3. 找到一种方法来解决您的问题,而无需在字典中存储"null"键.例如,考虑不在字典中填充null键并使用一些特殊的案例逻辑来处理它.密钥必须是可清除的并且与底层实现相当,这就是为什么通常禁止null的原因.

顺便说一句,你的词典密钥真的需要密钥object吗?这可能会导致细微的错误,因为您可能希望将Equals()作为比较的基础进行评估.


jes*_*tro 5

这个怎么样?

public class NullableDictionnary<T1, T2> : Dictionary<T1, T2>
{
    T2 null_value;

    public T2 this[T1 key]
    {
        get
        {
            if (key == null)
            { return null_value; }
            return base[key];
        }
        set
        {
            if (key == null)
            { null_value = value; }
            else
            { base[key] = value; }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 警惕你现在已经失效的所有其他功能 - Count,Add,Clear,ContainsKey,ContainsValue等...我的意思是,如果你只是黑客,好吧,但我不喜欢创建一个"NullableDictionary"的想法上课,如果你打算这样做.当一个黑客显然是一个黑客攻击时,你不太可能在以后得到它. (10认同)
  • 这不会编译 - ``Dictionary <TKey,TValue>``上的必需方法不是虚拟的.你必须将它作为一个单独的适配器来实现,它实现了``IDictionary <TKey,TValue>``. (2认同)