是否可以将对象用作Dictonary<object, ...>
的键,使得字典仅在对象相同时才将它们视为相等的对象?
例如,在下面的代码中,我希望第2行返回11而不是12:
Dictionary<object, int> dict = new Dictionary<object, int>();
object a = new Uri("http://www.google.com");
object b = new Uri("http://www.google.com");
dict[a] = 11;
dict[b] = 12;
Console.WriteLine(a == b); // Line 1. Returns False, because a and b are different objects.
Console.WriteLine(dict[a]); // Line 2. Returns 12
Console.WriteLine(dict[b]); // Line 3. Returns 12
字符串
当前的Dictionary实现在键上使用object.Equals()
和object.GetHashCode()
;但是我正在寻找一种不同类型的字典,它使用对象的标识作为键(而不是对象的值)。.NET中有这样的字典吗?或者我必须从头开始实现它?
5条答案
按热度按时间db2dz4w81#
你不需要构建自己的字典-你需要构建自己的
IEqualityComparer<T>
实现,它使用身份来进行哈希和相等。我不认为框架中存在这样的东西,但由于RuntimeHelpers.GetHashCode
,它很容易构建。字符串
我将
T
限制为引用类型,这样你就可以在字典中找到 objects;如果你将其用于值类型,你可能会得到一些奇怪的结果。(我不知道这是如何工作的;我怀疑 * 它不会。)有了这些,剩下的就简单了。例如:
型
2j4z5cfb2#
当然,其他的答案是完全正确的,但我写了我自己的版本,以满足我的需要:
字符串
设计原理:
sealed
。如果这个类不是为扩展而设计的,我将通过密封它来避免所有这些开销。
我知道很多人(包括我自己)认为类确实应该在默认情况下被密封。
Instance
static read-only property来公开这个类的单个示例。Object.ReferenceEquals()
而不是==
,因为ReferenceEquals
更显式。RuntimeHelpers.GetHashCode()
是因为我不想使用对象的可能被覆盖的GetHashCode
,这可能与ReferenceEquals
的行为不匹配。q5lcpyga3#
从5.0开始,
ReferenceEqualityComparer
现在随运行时一起提供。b4lqfgs44#
使用自己的相等比较器
字符串
请注意,
GetHashCode
可以被覆盖,但关键的检查是用Equals
进行的。正如@KyleMcClellan在他的answer中指出的那样,在.NET 5.0中添加了一个ReferenceEqualityComparer Class(命名空间:
System.Collections.Generic
)。你可以通过它的静态属性
Instance
获取一个示例。在VS中按F12可以检查源代码。Equals
调用ReferenceEquals(x, y)
,GetHashCode
调用RuntimeHelpers.GetHashCode(obj!)
。q9rjltbz5#
使用
Dictionary
withIEqualityComparer<TKey>
comparer