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

  • 相关阅读:
    分库分表就能无限扩容吗?
    每天数十亿次请求的应用经验分享,值得参考!
    QPS、TPS、并发用户数、吞吐量
    Django优雅集成MongoDB
    Linux apt-get
    Python Tenacity 实现"重试机制"
    Kubernetes 系列(一):Kubernetes 介绍、架构、安装
    MongoDB学习笔记:文档Crud Shell
    ubuntu下快速安装rabbitmq
    Reactor模型详解:单Reactor多线程与主从Reactor多线程
  • 原文地址:https://www.cnblogs.com/Abbey/p/2103591.html
Copyright © 2020-2023  润新知