• 关于显式进行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()。

  • 相关阅读:
    warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
    Windows10+CLion+OpenCV4.5.2开发环境搭建
    Android解决部分机型WebView播放视频全屏按钮灰色无法点击、点击全屏白屏无法播放等问题
    MediaCodec.configure Picture Width(1080) or Height(2163) invalid, should N*2
    tesseract
    Caer -- a friendly API wrapper for OpenCV
    Integrating OpenCV python tool into one SKlearn MNIST example for supporting prediction
    Integrating Hub with one sklearn mnist example
    What is WSGI (Web Server Gateway Interface)?
    Hub --- 机器学习燃料(数据)的仓库
  • 原文地址:https://www.cnblogs.com/Abbey/p/2103591.html
Copyright © 2020-2023  润新知