IComparable 是在字典中强制使用唯一键的最佳方式吗?
Is IComparable the best way to use to enforce unique keys in Dictionary?
我有一个 class MyClass,我想将它作为字典的键,如下所示:
Dictionary<MyClass, string> dict = new Dictionary<MyClass, string>();
我想保证MyClass是唯一键,唯一性是通过查看MyClass.UniqueProperty
指定的。我的第一个想法是重载 ==
运算符,但我发现 C# 不允许这样做。然后我找到了 IComparable 接口。这会成功吗?或者我应该重载 Object.Equals(obj)?
Is IComparable
the best way to use to enforce unique keys in Dictionary?
否 - IComparable
用于查看一个对象是否大于、等于或小于另一个对象。它主要用于排序例程。它可以用来判断两个对象是否相等,但它不是"best"方式。
Or should I overload Object.Equals(obj)
?
是的。您还可以实现 IEquatable<T>
,如果您已经适当地覆盖了 Equals
(和 GetHashCode
),这通常是微不足道的。
请注意,如果您将对象用作散列键,则 GetHashCode
的实现至关重要。需要遵循 many guidelines 来实现正确的散列例程,而且只比较相等性比较棘手。
My first thought was to overload the ==
operator, but I found that C# does not allow this.
嗯,你可以,但它不适合你正在做的事情。 ==
运算符通常用于 reference 相等,意思是 "do these two variables point to the same instance"。 Object.Equals
更适合value相等,意思是"are these two objects really describing the same thing"
词典已为自定义平等规则做好了充分准备。这就是为什么它有一个构造函数需要 IEqualityComparer
(https://msdn.microsoft.com/en-us/library/ms132072(v=vs.110).aspx).
由于您只关心字典上下文中的相等性,IEqualityComparer<MyClass>
是最直接的解决方案。
原始示例:
void Main()
{
var dict = new Dictionary<MyClass, string>(new MyClassUniqueIdEqualityComparer());
dict.Add(new UserQuery.MyClass { UniqueId = 1 }, "Hi!");
dict.ContainsKey(new UserQuery.MyClass { UniqueId = 2 }).Dump(); // False
dict.ContainsKey(new UserQuery.MyClass { UniqueId = 1 }).Dump(); // True
}
public class MyClass
{
public int UniqueId { get; set; }
}
public class MyClassUniqueIdEqualityComparer : IEqualityComparer<MyClass>
{
public bool Equals(MyClass a, MyClass b)
{
return a.UniqueId == b.UniqueId;
}
public int GetHashCode(MyClass a)
{
return a.UniqueId.GetHashCode();
}
}
主要好处是相等规则仅适用于相等比较器定义的情况。您不必确保例如之间的适当平等。派生的 class 和基础的 class - 这一切都在字典和比较器的约定之内。由于 Equals
和 GetHashCode
方法对于字典而言不是虚拟的,因此它们甚至允许不同类型之间的相等性,只要它们实现相同的接口——这是你真的不想做的object.Equals
、IEquatable<T>
和 IComparable<T>
.
我有一个 class MyClass,我想将它作为字典的键,如下所示:
Dictionary<MyClass, string> dict = new Dictionary<MyClass, string>();
我想保证MyClass是唯一键,唯一性是通过查看MyClass.UniqueProperty
指定的。我的第一个想法是重载 ==
运算符,但我发现 C# 不允许这样做。然后我找到了 IComparable 接口。这会成功吗?或者我应该重载 Object.Equals(obj)?
Is
IComparable
the best way to use to enforce unique keys in Dictionary?
否 - IComparable
用于查看一个对象是否大于、等于或小于另一个对象。它主要用于排序例程。它可以用来判断两个对象是否相等,但它不是"best"方式。
Or should I overload
Object.Equals(obj)
?
是的。您还可以实现 IEquatable<T>
,如果您已经适当地覆盖了 Equals
(和 GetHashCode
),这通常是微不足道的。
请注意,如果您将对象用作散列键,则 GetHashCode
的实现至关重要。需要遵循 many guidelines 来实现正确的散列例程,而且只比较相等性比较棘手。
My first thought was to overload the
==
operator, but I found that C# does not allow this.
嗯,你可以,但它不适合你正在做的事情。 ==
运算符通常用于 reference 相等,意思是 "do these two variables point to the same instance"。 Object.Equals
更适合value相等,意思是"are these two objects really describing the same thing"
词典已为自定义平等规则做好了充分准备。这就是为什么它有一个构造函数需要 IEqualityComparer
(https://msdn.microsoft.com/en-us/library/ms132072(v=vs.110).aspx).
由于您只关心字典上下文中的相等性,IEqualityComparer<MyClass>
是最直接的解决方案。
原始示例:
void Main()
{
var dict = new Dictionary<MyClass, string>(new MyClassUniqueIdEqualityComparer());
dict.Add(new UserQuery.MyClass { UniqueId = 1 }, "Hi!");
dict.ContainsKey(new UserQuery.MyClass { UniqueId = 2 }).Dump(); // False
dict.ContainsKey(new UserQuery.MyClass { UniqueId = 1 }).Dump(); // True
}
public class MyClass
{
public int UniqueId { get; set; }
}
public class MyClassUniqueIdEqualityComparer : IEqualityComparer<MyClass>
{
public bool Equals(MyClass a, MyClass b)
{
return a.UniqueId == b.UniqueId;
}
public int GetHashCode(MyClass a)
{
return a.UniqueId.GetHashCode();
}
}
主要好处是相等规则仅适用于相等比较器定义的情况。您不必确保例如之间的适当平等。派生的 class 和基础的 class - 这一切都在字典和比较器的约定之内。由于 Equals
和 GetHashCode
方法对于字典而言不是虚拟的,因此它们甚至允许不同类型之间的相等性,只要它们实现相同的接口——这是你真的不想做的object.Equals
、IEquatable<T>
和 IComparable<T>
.