我正在尝试将(名称:字符串,值:长)对存储在一个集合中。
public class NameValuePair
{
public string name;
public long value;
}
public NameValuePairComparer comparer = new NameValuePairComparer();
public HashSet<NameValuePair> nameValueSet = new HashSet<NameValuePair>(comparer);
如果两个对具有相同的名称或相同的值,则它们相等 - 这是在 NameValuePairComparer 中实现的,重写 EqualityComparer 中的 Equals 方法:
public class NameValuePairComparer : EqualityComparer<NameValuePair>
{
public override bool Equals(NameValuePair x, NameValuePair y)
{
return (x.value == y.value) || (x.name == y.name);
}
问题是:GetHashCode(NameValuePair obj) 对于 Equals 返回 true 的两个对象应该返回相同的值,因此对于给定的 NameValuePair,GetHashCode() 应该返回 value.GetHashCode() 或 name.GetHashCode(),但是为此,我们必须知道两对中的哪个字段相等:
public override int GetHashCode(NameValuePair obj)
{
/* ??? */
/* // Using unknown reference to x
if (obj.value == x.value) return obj.value.GetHashCode();
else if (obj.name == x.name) return obj.name.GetHashCode();
else return base.GetHashCode(obj);
*/
}
}
但是我们无法知道这一点,这意味着我无法使用 HashSet 来存储这些对,也无法使用 EqualityComparer。
问:C# (.net 3.5) 中是否有基于非哈希的 set 实现?
问:使用自定义相等比较器存储唯一 NameValuePairs 的更好方法是什么?
最佳答案
Two pairs are equal if either they have equal name or equal value
你根本无法实现 IEqualityComparer<T>
正确地符合这些标准。来自Equals
的文档:
The Equals method is reflexive, symmetric, and transitive. That is, it returns true if used to compare an object with itself; true for two objects x and y if it is true for y and x; and true for two objects x and z if it is true for x and y and also true for y and z.
现在考虑配对:
x = { "A", 10 },
y = { "A", 20 },
z = { "B", 20 }
你是说x
和y
必须相等,因为它们具有相同的名称,并且 y
和z
必须相等,因为它们具有相同的值。这意味着(通过传递性)x
和z
应该是相等的。
因为你无法实现 IEqualityComparer<T>
正确地说,您不应该期望任何依赖于该正确性的东西都能工作。
我怀疑您会发现,如果您更详细地了解您的需求,它们要么真正需要两个集合(一个按名称,一个按值)或> 从传递性的角度来看,它们没有意义。
例如,假设您有一个具有您建议的特征的集合,然后添加上面的三个元素。如果您按照 { x, y, z } 的顺序添加它们,您最终会得到一个条目。如果你按照 { z, x, y } 的顺序添加它们,你最终会得到两个。这是一个有用的集合吗?
关于c# - 非基于哈希的集合集合,用于使用自定义相等比较器存储唯一对象 - C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15474710/