《C#高效编程》读书笔记06-理解几个等同性判断之间的关系

当创建自定义类型时(无论是class还是struct),应为类型定义"等同性"的含义。C#提供了4种不同的函数来判断两个对象是否"相等":

public static bool ReferenceEquals(object left, object right);
public static bool Equals(object left, object right);
public virtual bool Equals(object right);
public static bool operator ==(MyClass left, MyClass right);

Object.ReferenceEquals()Object.Equals()这两个系统提供的静态方法,永远都不需要重新定义。

Object.ReferenceEquals()判断的是对象引用,判断的是否拥有同样的对象标识(object identity),所以若将一个值类型与它自身进行比较,方法返回的是false,因为值类型会进行装箱操作,造成引用地址不同。

Object.Equals()对于引用类型默认使用对象标识判断,即跟Object.ReferenceEquals()一样,但对于值类型,因为System.ValueType重写了Object.Equals()方法,所以比较的是值是否相等(主要是struct),但System.ValueType是所有值类型的基类,故实现比较时,用的是反射,效率并不高。

综上所述,自定义类型实现自己的比较方法就比较重要了。

public class Student : IEquatable<Student>
{
    public int Id { get; set; }
    public string Name { get; set; }

    public override bool Equals(object obj)
    {
        if (Object.ReferenceEquals(obj, null))
            return false;
        if (Object.ReferenceEquals(this, obj))
            return true;
        if (this.GetType() != obj.GetType())
            return false;

        return this.Equals(obj as Student);
    }

    public bool Equals(Student other)
    {
        if (this.Id != other.Id)
            return false;
        if (this.Name != other.Name)
            return false;

        return true;
    }
}

注意,重写Equals方法时,需要同时重写GetHashCode()方法,详细可查看条目7。

operator==()则相对简单。只要创建的是值类型,都必须重定义operator==()。理由和重写System.ValueType的Equals是一样的。而引用类型则应该避免重写operator==()

posted @ 2017-04-26 10:27  爱幻想の宅  阅读(279)  评论(0编辑  收藏  举报