zoukankan      html  css  js  c++  java
  • 关于显式进行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()。

  • 相关阅读:
    单词统计
    意见汇总
    项目评审结果
    注册表键值
    C++ 创建快捷方式
    XPosed 示例
    直播流程
    C++隐藏任务栏图标
    C++ 屏幕录制
    DUILIB UI创建过程
  • 原文地址:https://www.cnblogs.com/Abbey/p/2103591.html
Copyright © 2011-2022 走看看