国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

如何使用==操作符,Equals方法,ReferenceEquals方法,IEquatable接口比較2個對象

2019-11-14 16:29:39
字體:
來源:轉載
供稿:網友

“世界上不會有兩片完全相同的樹葉”,這句話適用于現實世界。而在軟件世界中,這句話變成了"世界上必須有兩片完全相同的樹葉",否則,很多事情無以為繼。

 

當比較2個對象是否相等時,通常情況下:==操作符用來比較值類型,比較的是值;實例方法Equals和靜態方法Object.ReferenceEquals比較引用類型,比較的是對象的地址。

 

在實際項目中,當比較2個引用類型對象時,我們的需求變為:通過依次比較2個對象的所有屬性來判斷是否相等。這時候,IEquatable接口就有了展示自己的機會。本篇主要包括:

 

  • 使用==操作符比較值類型是否相等
  • 實例方法Equals比較引用類型地址是否相等
  • 實現IEquatable接口重寫實例方法Equals()

 

  使用==操作符比較值類型是否相等

    class PRogram
    {
        static void Main(string[] args)
        {
            ComplexNumber a = new ComplexNumber(){Real = 4.5D, Imaginary = 8.4D};
            ComplexNumber b = new ComplexNumber() { Real = 4.5D, Imaginary = 8.4D };
            Console.WriteLine("{0} 是否等于{1}:{2}",a, b, CompareTwoComplexNumbers(a, b));
            Console.ReadKey();
        }
        static bool CompareTwoComplexNumbers(ComplexNumber a, ComplexNumber b)
        {
            return ((a.Real == b.Real) && (a.Imaginary == b.Imaginary));
        }
    }
    public class ComplexNumber
    {
        public double Real { get; set; }
        public double Imaginary { get; set; }
        public override string ToString()
        {
            return String.Format("{0}{1}{2}i",
                Real,
                Imaginary >= 0 ? "+" : "-",
                Math.Abs(Imaginary));
        }
    }

1


以上,比較諸如int,double,DateTime,struct等值類型的時候,==操作符當然是不二之選。

 

  實例方法Equals比較引用類型地址是否相等

    class Program
    {
        static void Main(string[] args)
        {
            Guy darren1 = new Guy("Darren", 37, 100);
            Guy darren2 = darren1;
            Console.WriteLine(Object.ReferenceEquals(darren1,darren2));
            Console.WriteLine(darren1.Equals(darren2));
            Console.WriteLine(Object.ReferenceEquals(null, null));
            darren2 = new Guy("Darren", 37, 100);
            Console.WriteLine(Object.ReferenceEquals(darren1, darren2));
            Console.WriteLine(darren1.Equals(darren2));
            Console.ReadKey();
        }
    }
    public class Guy
    {
        private readonly string name;
        public string Name{get { return name; }}
        private readonly int age;
        public int Age{get { return age; }}
        public int Cash { get; private set; }
        public Guy(string name, int age, int cash)
        {
            this.name = name;
            this.age = age;
            Cash = cash;
        }
        public override string ToString()
        {
            return String.Format("{0} 今年 {1} 歲了,身價{2}", Name, Age, Cash);
        }
    }

2

以上,實例方法Equals()和靜態方法Object.ReferenceEquals()適用于比較引用類型,而且比較的是對象的地址。


可是,如果我們想使用Equals()方法比較引用類型對象的各個屬性,怎么辦呢?

 

  實現IEquatable接口重寫實例方法Equals()

寫一個派生于Guy的類EquatableGuy,并且實現IEquatable<Guy>接口,重寫IEquatable<Guy>接口的Equals(Guy other)方法。

   class Program
    {
        static void Main(string[] args)
        {
            Guy darren1 = new EquatableGuy("Darren", 37, 100);
            Guy darren2 = new EquatableGuy("Darren", 37, 100);
            Console.WriteLine(Object.ReferenceEquals(darren1, darren2)); //False
            Console.WriteLine(darren1.Equals(darren2)); //True
            Console.ReadKey();
        }
    }
    public class Guy
    {
        private readonly string name;
        public string Name{get { return name; }}
        private readonly int age;
        public int Age{get { return age; }}
        public int Cash { get; private set; }
        public Guy(string name, int age, int cash)
        {
            this.name = name;
            this.age = age;
            Cash = cash;
        }
        public override string ToString()
        {
            return String.Format("{0} 今年 {1} 歲了,身價{2}", Name, Age, Cash);
        }
    }
    public class EquatableGuy : Guy, IEquatable<Guy>
    {
        public EquatableGuy(string name, int age, int cash) : base(name, age, cash){}
        public bool Equals(Guy other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            return Equals(other.Name, Name) && other.Age == Age && other.Cash == Cash;
        }
        public override bool Equals(object obj)
        {
            if (!(obj is Guy)) return false;
            return Equals((Guy) obj);
        }
        public override int GetHashCode()
        {
            const int prime = 397;
            int result = Age;
            result = (result * prime) ^ (Name != null ? Name.GetHashCode() : 0);
            result = (result * prime) ^ Cash;
            return result;
        }
    }

3

 

以上,值得注意的是:
當實現IEquatable<Guy>接口時,一定要重寫Object基類的Equals方法,然后在Object基類的Equals方法內部調用我們自定義的IEquatable<Guy>接口方法。另外還必須重寫Object基類的GetHashCode方法。這時MSDN規定的,
在這里。

 

而且,使用IEquatable<Guy>泛型接口還有一個好處是避免裝箱和拆箱,因為在JIT編譯時才替代占位符。而如果我們通過重寫Object基類方法Equals實現自定義比較的話,難免會出現裝箱和拆箱,影響比較性能。


如果我們項使用==操作符比較引用對象是否相等呢?我們可以通過重寫操作符來實現。

 

我們再寫一個EquatableGuy的子類EquatableGuyWithOverload,并且重寫==操作符。

   class Program
    {
        static void Main(string[] args)
        {
            var darren1 = new EquatableGuyWithOverload("Darren", 37, 100);
            var darren2 = new EquatableGuyWithOverload("Darren", 37, 100);
            Console.WriteLine(Object.ReferenceEquals(darren1, darren2)); //False
            Console.WriteLine(darren1 == darren2); //True
            Console.ReadKey();
        }
    }
    public class EquatableGuyWithOverload : EquatableGuy
    {
        public EquatableGuyWithOverload(string name, int age, int cash) : base(name, age, cash){}
        public static bool Operator ==(EquatableGuyWithOverload left, EquatableGuyWithOverload right)
        {
            if (Object.ReferenceEquals(left, null)) return false;
            else return left.Equals(right);
        }
        public static bool operator !=(EquatableGuyWithOverload left, EquatableGuyWithOverload right)
        {
            return !(left == right);
        }
        public override bool Equals(object obj)
        {
            return base.Equals(obj);
        }
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
    }

3

 

以上,子類EquatableGuyWithOverload重寫了==操作符,由于其父類EquatableGuy已經重寫了基類Object的Equals方法,所以在這里可以直接調用。

 

總結:通常情況下,使用==操作符比較值類型對象;使用實例方法Equals或靜態方法Object.ReferenceEquals比較引用類型對象地址;如果想自定義比較邏輯,可以考慮實現IEquatable<>泛型接口,避免裝箱、拆箱。

 

參考資料:

防止裝箱落實到底,只做一半也是失敗
Understanding C#: Equality, IEquatable, and Equals()
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 青冈县| 临清市| 滕州市| 方山县| 旬邑县| 嘉黎县| 林州市| 巴马| 巴青县| 平陆县| 龙江县| 咸阳市| 阜城县| 黄浦区| 黄梅县| 崇仁县| 湄潭县| 隆子县| 伽师县| 潜江市| 新宁县| 海伦市| 甘洛县| 台安县| 徐闻县| 托克托县| 德州市| 元阳县| 永吉县| 诸暨市| 胶南市| 莲花县| 札达县| 湛江市| 文水县| 无棣县| 布拖县| 锦屏县| 吴旗县| 奉节县| 综艺|