关于显式进行object类型转换后进行比较的讨论

一、讨论的起因

先看如下的一段代码:

string s1 = "123";
string s2 = "123";
Console.WriteLine(object.ReferenceEquals(s1, s2));
Console.WriteLine(s1 == s2);
Console.WriteLine((object) s1 == (object) s2);

运行结果:

True  
True  
True

第一个True:ReferenceEquals使用两个引用的内存地址进行比较。上例中声明了两个相同的字符串变量,编译器会将它们存储在同一位置,所以这两个字符串实际引用内存中的同一对象。这个没有争议。
第二个True:利用string对==的重载完成字符串比较,同样没有争议。

二、讨论的重点

争议的重点是第三个True。存在如下两种观点:

意见A: 这是类似于ReferenceEquals的比较,等价于前述第一个True,没有更多的细节。

意见B (我的观点): 基本同意意见A,但由于(object)s1==(object)s2 与 ((object)s1).Equals((object)s2)在语义上的相近,都可以理解为比较2个object是否相等,所以很容易掉进一个语义上的陷阱: ==比较不相等,Equals()比较能相等。

以下是我的一段模拟代码:

using System;

namespace EqualsTest
{
    class MainClass
    {
        public static void Main(string[] args)
        {
            SomeClass a = new SomeClass() { _name = "123" };
            SomeClass b = new SomeClass() { _name = "123" };
            Console.WriteLine(a == b);
            Console.WriteLine((object) a == (object) b);
            Console.WriteLine(((object) a).Equals((object) b));
        }
    }

    class SomeClass : Object
    {
        public string _name = null;
        public override bool Equals(object obj)
        {
            Console.WriteLine("Call in SomeClass.Equals...");
            return _name == ((SomeClass) obj)._name;
        }
        public static bool operator ==(SomeClass a, SomeClass b)
        {
            Console.WriteLine("Call in SomeClass...");
            return a.Equals(b);
        }
        public static bool operator !=(SomeClass a, SomeClass b)
        {
            Console.WriteLine("Call in SomeClass...");
            return !a.Equals(b);
        }
    }
}

运行结果:

Call in SomeClass...  
Call in SomeClass.Equals...  
True  
False  
Call in SomeClass.Equals...  
True

在这段模拟代码里,==与Equals()不再等价。造成差别的原因,就在于SomeClass重写(Override)了Object的 Equals()方法,从而利用动态联编特性在运行时取代了Object.Equals()。而另一方面,操作符==是专属于类的static重载,因此无法在运行时被其子类取代。

附上Object.Equals()方法原型:

public virtual bool Equals(Object obj);

三、结论

为了避免类似这样的问题,应当避免在用object进行强制类型转换后使用==这样的比较,而应选择object.ReferenceEquals()。

原文地址:https://www.cnblogs.com/Abbey/p/2103591.html