比较在Dictionary中用作Key的对象
我的课:
public class myClass { public int A { get; set; } public int B { get; set; } public int C { get; set; } public int D { get; set; } }
和主要的例子:
Dictionary<myClass, List> dict = new Dictionary<myClass, List>(); myClass first = new myClass(); first.A = 2; first.B = 3; myClass second = new myClass(); second.A = 2; second.B = 3; second.C = 5; second.D = 6; dict.Add(first, new List()); if (dict.ContainsKey(second)) { // //should come here and update List for first (and only in this example) key // } else { // //if myFirst object has difference vlues of A or B properties // dict.Add(second, new List()); }
这该怎么做?
如果您始终只希望字典在A和B上进行比较,则有两种选择。 使用实现IEqualityComparer
的构造函数并将比较逻辑放在那里,或者让你的类实现 GetHashCode和Equals,这样默认的比较器将为你提供你想要的结果。 IEquateable
如果您只想在一种情况下比较A和B,则需要使用.Keys比例和Linq扩展方法Contains ,它允许您传入IEqualityComparer
。 但是,当这样做时,你会失去使用Dictionary的速度优势,所以请谨慎使用它。
public class MyClassSpecialComparer : IEqualityComparer { public bool Equals (myClass x, myClass y) { return xA == yA && xB == yB } public int GetHashCode(myClass x) { return xAGetHashCode() + xBGetHashCode(); } } //Special case for when you only want it to compare this one time //NOTE: This will be much slower than a normal lookup. var myClassSpecialComparer = new MyClassSpecialComparer(); Dictionary> dict = new Dictionary>(); //(Snip) if (dict.Keys.Contains(second, myClassSpecialComparer )) { // //should come here and update List for first (and only in this example) key // } //If you want it to always compare Dictionary> dict = new Dictionary>(new MyClassSpecialComparer());
默认情况下,比较会根据哈希代码将对象放入存储桶。 如果两个哈希码相同,则执行详细比较(通过调用Equals
)。 如果您的类既不提供GetHashCode
也不实现相等,则将使用默认的object.GetHashCode
– 在这种情况下,您的类的任何特定内容都不会用于值比较语义。 只会找到相同的参考。 如果您不想这样做,请实现GetHashCode
并实现相等性。
例如:
public class myClass { public int A { get; set; } public int B { get; set; } public int C { get; set; } public int D { get; set; } public bool Equals(myClass other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return other.A == A && other.B == B && other.C == C && other.D == D; } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; if (obj.GetType() != typeof (myClass)) return false; return Equals((myClass) obj); } public override int GetHashCode() { unchecked { int result = A; result = (result*397) ^ B; result = (result*397) ^ C; result = (result*397) ^ D; return result; } } }
在myClass中覆盖:
-
GetHashCode方法
-
等于方法
要实现GetHashCode方法,您只需从整数属性中XOR GetHashCodes即可。
(可选)覆盖ToString方法并实现IEquatable接口