代码之家  ›  专栏  ›  技术社区  ›  Clyde

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

  •  13
  • Clyde  · 技术社区  · 16 年前

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

    Dictionary<object, string> dict = new Dictionary<object, string>();
    dict.Add(null, "Nothing");
    dict.Add(1, "One");
    

    在基类库中是否有允许这样做的内置组件?前面的代码将在运行时添加空键时引发异常。

    谢谢

    5 回复  |  直到 12 年前
        1
  •  11
  •   LBushkin    16 年前

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

    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");
    

    如果您打算使集合更加强类型化,那么这种方法将无法工作——例如,您希望键是字符串。因为字符串是密封的,所以不能从中继承来创建“特殊值”来替代空值。你的选择变得有点复杂。你可以:

    1. 创建一些特殊的常量值来表示“空”/“空”大小写。有点老土,绝对是一条迷茫之路。如果字典对某些实现类是完全私有的,并且您可以编写一些编码/解码实用程序方法,以避免在各处传播如何翻译密钥的知识,那么这是一种可行的方法。
    2. 创建自己的IDictionary实现,该实现在内部委托给Dictionary<gt;实例-空的情况除外。这违反了对IDictionary<gt;接口的文档化期望,后者确实表示空键应引发异常。但是,如果这是解决你真正问题的唯一方法,你也许可以摆脱它。只有当您拥有并创建字典实例时,这才有效。
    3. 找到一种不在字典中存储“空”键的方法来解决您的问题。例如,考虑不在字典中填充空键,并使用一些特殊的事例逻辑来处理它。键必须是可散列的,并且可以与底层实现进行比较,这就是为什么通常禁止使用空值的原因。

    作为旁白,你的字典键真的需要 object ?这可能会导致细微的错误,因为在使用引用相等时,您可能希望使用equals()作为比较的基础。

        2
  •  5
  •   jestro    16 年前

    这个怎么样?

    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; }
            }
        }
    }
    
        3
  •  2
  •   Josh    16 年前

    NameValueCollection可以接受空键,但不实现IDictionary。然而,从DictionaryBase派生并提供添加/删除/索引器等非常容易,这些添加/删除/索引器等只需将空值替换为内置的内容,例如:

    class MyDictionary : DictionaryBase {
        private readonly object nullKey = new object();
    
        void Add(object key, string value) {
           if ( key == null ) { key = nullKey; }
           .. call base methods
        }
    
    }
    
        4
  •  0
  •   user164226    16 年前

    键是否需要为空?集合中的键是一个索引。对于我来说,集合中索引的空值没有多大意义。

    可能创建一个新类

    
    public class ObjectEntry
    {
        public object objRef;
        public string desc;
    
        public ObjectEntry(object objectReference)
        {
            objRef = objectReference;
            if (objRef = null) {desc = "Nothing";}
            else {desc = objRef.Description;} //or whatever info you can get from a proper objRef value
        }
    }
    
    newObj = new ObjectEntry(null);
    dict.add(newObj, newObj.desc);
    
        5
  •  0
  •   Community Mohan Dere    9 年前

    不需要另一种执行方式。

    看看我的答案: https://stackoverflow.com/a/22261282/212272

    您还可以将字典保持为强类型:

    var dict = new Dictionary<NullObject<int?>, string>();
    dict[1] = "one int";
    dict[null] = "null int";
    
    Assert.AreEqual("one int", dict[1]);
    Assert.AreEqual("null int", dict[null]);