为什么不能将null用作Dictionary <bool?,string>的键?

dev*_*xer 67 .net c# dictionary hashtable

显然,null即使您的密钥是可空类型,也不能使用密钥.

这段代码:

var nullableBoolLabels = new System.Collections.Generic.Dictionary<bool?, string>
{
    { true, "Yes" },
    { false, "No" },
    { null, "(n/a)" }
};
Run Code Online (Sandbox Code Playgroud)

...导致此异常:

值不能为空.参数名称:key

描述:执行当前Web请求期间发生未处理的异常.请查看堆栈跟踪以获取有关错误及其源自代码的位置的更多信息.

[ArgumentNullException: Value cannot be null. Parameter name: key] System.ThrowHelper.ThrowArgumentNullException(ExceptionArgument argument) +44 System.Collections.Generic.Dictionary'2.Insert(TKey key, TValue value, Boolean add) +40
System.Collections.Generic.Dictionary'2.Add(TKey key, TValue value) +13

为什么.NET框架允许键的可空类型,但不允许空值?

Dyn*_*ard 36

它会告诉你同样的事情,如果你有一个Dictionary<SomeType, string>,SomeType作为一个引用类型,并且你试图传递null作为键,它不是只影响可空类型的东西bool?.您可以使用任何类型作为键,可以为空或者为空.

这一切都归结为你无法真正比​​较的事实nulls.我假设背后的逻辑不能放入null密钥,一个旨在与其他对象进行比较的属性是它使得比较null引用的语法不连贯.

如果你想从规范中得到一个理由,它归结为MSDN上的"A key不能是空引用" .

如果你想要一个可能的解决方法的例子,你可以尝试类似于需要一个允许空键的IDictionary实现

  • 错误.您可以在Nullable <bool>上调用GetHashcode设置为null.结果是0. (5认同)
  • 应该允许Null作为密钥.它的哈希码显然应该为零,你可以在C#中将null与null进行比较就好了; 他们是平等的.这不是TSQL的一些奇怪的null!= null概念.这种实施很糟糕.例如,我想从item-> parent关系的平面列表构建一个树,所以我想调用`items.GroupBy(x => x.ParentId).ToDictionary(x => x.Key,x.ToList ())`,但我不能,因为根节点的ParentId为null,虽然它可以将GroupBy值为null,但它拒绝允许它作为字典中的键.荒谬.J/K (3认同)
  • 不过,您可以将 null 传递给 IEQualityComparer 的 GetHashCode(),因此您一定可以获得 null 的哈希码。 (2认同)

Mah*_*dsi 14

通常,您必须回到C++方法和技术,以完全理解.NET Framework以特定方式工作的方式和原因.

在C++中,您经常需要选择一个不会被使用的键 - 字典使用此键指向已删除和/或空的条目.例如,您有一个字典<int, int>,在插入条目后,您将其删除.而不是当时和那里运行垃圾清理,重组字典,并导致糟糕的表现; 字典将只用你之前选择的键替换KEY值,基本上意思是"当你遍历字典memoryspace时,假装这<key,value>对不存在,可以随意覆盖它."

这样的密钥也用于以特定方式在桶中预分配空间的字典 - 您需要一个键来"初始化"桶,而不是为每个条目指定一个标志,指示其内容是否有效.所以不是有一个三元<key, value, initialized><key, value>,你会得到一个规则的元组,如果key == empty_key那么它还没有被初始化 - 因此你可能不会使用empty_key作为有效的KEY值.

您可以在此处的文档中的Google哈希表(适用于.NET的人员:)中查看此类行为:http://google-sparsehash.googlecode.com/svn/trunk/doc/dense_hash_map.html

看看set_deleted_keyset_empty_key函数来得到我正在谈论的内容.

我打赌.NET使用NULL作为唯一的deleted_key或empty_key,以便做这些提高性能的漂亮技巧.

  • ......是的; 让我试着改写一下.那么什么是用于标记已删除条目的"将不会被使用的密钥"呢?除非内部键类型是选中的值为"Nullable <T>"的值,否则没有可用键,因为所有键都有效.没有? (2认同)