- Consider overriding Equals if the semantics of the type are based on the fact that the type represents some value(s).
(当你要重载引用形式的equal的时候,你要比较的两个值得语义必须是引用类型)
- Most reference types must not overload the equality operator, even if they override Equals. However, if you are implementing a reference type that is intended to have value semantics, such as a complex number type, you must override the equality operator.
(当你重载了一个引用类型的equal方法的时候,一定不要重载相等运算符==;当你重载的是值类型的equal方法时候,必须重载相等运算符。)
- You should not override Equals on a mutable reference type. This is because overriding Equals requires that you also override the GetHashCode method, as discussed in the previous section. This means that the hash code of an instance of a mutable reference type can change during its lifetime, which can cause the object to be lost in a hash table.
(※不能把Equal方法重载到一个地址可变的量上(因为重载了equal函数我们必须重载GetHashCode方法),一个实例可变引用的散列值会随着他的生存期会一直改变,这会导致我们无法在散列表中找到这个对象。)
- If you are defining a value type that includes one or more fields whose values are reference types, you should override Equals(Object). The Equals(Object) implementation provided by ValueType performs a byte-by-byte comparison for value types whose fields are all value types, but it uses reflection to perform a field-by-field comparison of value types whose fields include reference types.
(如果你自定义了一个值类型,且这个值类型含有引用类型,那么你必须重载Equal方法,在值类型中,Equal方法对于值类型中的值类型的比较是值与值之间的比较(内存中byte o byte),引用类型比较的是两个对象是否指向同一个内存地址)
- If you override Equals and your development language supports operator overloading, you must overload the equality operator.
(如果你重载了值类型的Equal方法,那么你一定要重载相等运算符)
- You should implement the IEquatable<T> interface. Calling the strongly typed IEquatable<T>.Equals method avoids boxing the obj argument.
(如果你重载了值类型Equal方法,推荐同时实现IEquatable<T> 接口,比较时使用IEquatable<T> 接口而不是把实例封箱到Object中)。(值类型的重载也是要重载GetHashCode的。)
- x.Equals(x) returns true. This is called the reflexive property.(自己等于自己为真)
- x.Equals(y) returns the same value as y.Equals(x). This is called the symmetric property.(可交换性)
- if (x.Equals(y) && y.Equals(z)) returns true, then x.Equals(z) returns true. This is called the transitive property.(可传递性)
- Successive invocations of x.Equals(y) return the same value as long as the objects referenced by x and y are not modified.(与引用无关)
- x.Equals(null) returns false. However, null.Equals(null) throws an exception; it does not obey rule number two above.(与null进行比较返回假)
struct结构隐式继承 System.ValueType,这个类已经重写了Object.Equals(Object)方法,但是这个重写过的方法是用的反射技术来检测所有的public和非public属性,尽管这个操作在struct类型里面用是正确的,但是这个操作是很慢的。换句话说,如果我们想自定义自己的值类型,最好是从class继承并改写Equals方法。
string str1 = "Fuck"; string str2 = "Fuck";
- Override the virtualObject.Equals(Object) method. In most cases, your implementation of bool Equals( object obj ) should just call into the type-specific Equals method that is the implementation of the System.IEquatable<T> interface. (See step 2.)
(重写Equals方法或者实现System.IEquatable<T>接口)
- Implement the System.IEquatable<T> interface by providing a type-specific Equals method. This is where the actual equivalence comparison is performed. For example, you might decide to define equality by comparing only one or two fields in your type. Do not throw exceptions from Equals. For classes only: This method should examine only fields that are declared in the class. It should call base.Equals to examine fields that are in the base class. (Do not do this if the type inherits directly from Object, because the Object implementation of Object.Equals(Object) performs a reference equality check.)
(System.IEquatable<T>接口里面可以仅实现部分比较,但绝对不要在Equals里面抛出异常,如果比较的对象有基类,必须调用base.Equals方法)
- Optional but recommended: Overload the == and != operators.
(最好重载==和!=运算符(同时实现))
- Override Object.GetHashCode so that two objects that have value equality produce the same hash code.
(必须重写Object.GetHashCode)
- Optional: To support definitions for "greater than" or "less than," implement the IComparable<T> interface for your type, and also overload the <= and >= operators.
(大于小于号这些可选,比如复数类的时候就需要这些运算符重载)。
class Test1 { public string Name { get; set; } public Test1(string name) { Name = name; } public override bool Equals(object obj) { if (obj == null || obj.GetType() != typeof(Test1)) return false; Test1 testObj = obj as Test1; return this.Name == testObj.Name; } public static bool operator==(Test1 t1, Test1 t2) { return t1.Equals(t2); } public static bool operator !=(Test1 t1, Test1 t2) { return !(t1 == t2); } public override int GetHashCode() { return base.GetHashCode(); } }
这个时候我们可以把Test1来进行值的比较了,但是上面的代码并没有真正重载GetHashCode,以至于我们会导致下面的问题,我们写入下面的代码:
class Program { static void Main(string[] args) { Test1 t1 = new Test1("HaHa"); Test1 t2 = new Test1("HaHa"); Console.WriteLine("t1.Equals(t2)? {0}", t1.Equals(t2)); Console.WriteLine("t1 == t2? {0}", t1 == t2); List<Test1> list = new List<Test1>(); list.Add(t1); Console.WriteLine("list contains Test1(HaHa)? {0}", list.Contains(t2)); Console.ReadKey(); } }
class Program { static void Main(string[] args) { Test1 t1 = new Test1("HaHa"); Test1 t2 = new Test1("HaHa"); Console.WriteLine("t1.Equals(t2)? {0}", t1.Equals(t2)); Console.WriteLine("t1 == t2? {0}", t1 == t2); ICollection<Test1> list = new HashSet<Test1>(); list.Add(t1); Console.WriteLine("list contains Test1(HaHa)? {0}", list.Contains(t2)); Dictionary<Test1, int> dict = new Dictionary<Test1, int>(); dict.Add(t1, 2); Console.WriteLine("dict contains Test1(HaHa)? {0}", dict.Keys.Contains(t2)); Console.ReadKey(); } }
public override int GetHashCode() { return Name.GetHashCode(); }
class Test : IEquatable<Test> { public Test(string name) { Name = name; } public bool Equals(Test other) { return this.Name == other.Name; } public override bool Equals(object obj) { return base.Equals(obj); } public override int GetHashCode() { return Name.GetHashCode(); } public string Name { get; set; } }
struct Test1 { public string Name { get; set; } public Test1(string name) { Name = name; } public override bool Equals(object obj) { if (obj is Test1) { return this.Name == ((Test1)obj).Name; } return false; } public static bool operator==(Test1 t1, Test1 t2) { return t1.Equals(t2); } public static bool operator!=(Test1 t1, Test1 t2) { return !(t1.Equals(t2)); } public override int GetHashCode() { return Name.GetHashCode(); } }
原文:http://www.cnblogs.com/Philip-Tell-Truth/p/6275416.html