zoukankan      html  css  js  c++  java
  • 你必须知道的.Net 8.2.2 本质分析

    1 .Equals  静态方法 

    Equals 静态方法实现了对两个对象的相等性判别,其在 System.Object 类型中实现过程可以表 示为:

            public static bool Equals(object objA, object objB)
            {
                if (objA == objB)
                {
                    return true;
                }
                if ((objA != null) && (objB != null))
                {
                    return objA.Equals(objB);
                }
                return false;
            }

      对以上过程,可以小结为:首先比较两个类型是否为同一实例,如果是则返回 true;否则将 进一步判断两个对象是否都为 null,如果是则返回 true;如果不是则返回 objA 对象的 Equals 虚方 法的执行结果。

      所以,Equals 静态方法的执行结果,依次取决于三个条件:

      l 是否为同一实例。

      l 是否都为 null。

      l 第一个参数的 Equals 实现。

      因此,通常情况下 Equals 静态方法的执行结果常常受到判等对象的影响,例如有下面的测试 过程:

        class Program5
        {
            public static void Main(string[] args)
            {
                MyClassA objA = new MyClassA();
                MyClassB objB = new MyClassB();
                Console.WriteLine(Equals(objA, objB));
                Console.WriteLine(Equals(objB, objA));
                Console.ReadKey();
            }
        }
        class MyClassA
        {
            public override bool Equals(object obj)
            {
                return true;
            }
        }
        class MyClassB
        {
            public override bool Equals(object obj)
            {
                return false;
            }
        }

    //执行结果

    True

    False

      由执行结果可知,静态 Equals 的执行取决于==操作符和 Equals 虚方法这两个因素。因此,决 议静态 Equals 方法的执行,就要在自定义类型中覆写 Equals 方法和重载==操作符。

    还应注意到,.NET 提供了 Equals 静态方法可以解决两个值为 null 对象的判等问题,而使用 ob jA.Equals(object objB)来判断两个 null 对象会抛出 NullReferenceException 异常

    public static void Main()
    {
    object o = null;
    o.Equals(null);
    }

    2 .ReferenceEquals  静态方法

    ReferenceEquals 方法为静态方法,因此不能在继承类中重写该方法,所以只能使用 System.Ob ject 的实现代码,具体为:

    public static bool ReferenceEquals(object objA, object objB)
    {
    return (objA == objB);
    }

      可见,ReferenceEquals 方法用于判断两个引用是否指向同一个对象,也就是前文强调的引用 相等。因此以 ReferenceEquals 方法比较同一个类型的两个对象实例将返回 fasle,而.NET 认为 null 等于 null

      因此,ReferenceEquals 方法,只能用于比较两个引用类型,而以 ReferenceEquals 方法比较值 类型,必然伴随着装箱操作的执行,分配在不同地址的两个装箱的实例对象,肯定返回 false 结果

      从结果分析可知两次创建的 string 类型实例不仅内容相同,而且分享共同的内存空间,事实 上的确如此,这缘于 System.String 类型的字符串驻留机制,详细的讨论见 8.3 节“为什么特殊:str ing 类型解析”,在此我们必须明确 ReferenceEquals 判断引用相等的实质是不容置疑的。

    3 .Equals  虚方法

      Equals 虚方法用于比较两个类型实例是否相等,也就是判断两个对象是否具有相同的“值”, 在 System.Object 中其实现代码,可以表示为:

    public virtual bool Equals(object obj)
    {
    return InternalEquals(this, obj);
    }

    其中 InternalEquals 为一个静态外部引用方法,其实现的操作可以表示成:

    if (this == obj)
    return true;
    else
    return false;

      可见,默认情况下,Equals 方法和 ReferenceEquals 方法是一样的,Object 类中的 Equals 虚方 法仅仅提供了最简单的比较策略:如果两个引用指向同一个对象,则返回 true;否则将返回 false, 也就是判断是否引用相等。然而这种方法并未达到 Equals 比较两个对象值相等的目标,因此 Syste m.Object 将这个任务交给其派生类型去重新实现,可以说 Equals 的比较结果取决于类的创建者是 如何实现的,而非统一性约定。

      事实上,.NET 框架类库中有很多的引用类型实现了 Equals 方法用于比较值相等,例如比较两 个 System.String 类型对象是否相等,肯定关注其内容是否相等,判断的是值相等语义:

    4 .== 操作 符

      在.NET 中,默认情况下,操作符“==”在值类型情况下表示是否值相等,由值类型的根类 Syste m.ValueType 提供了实现;而在引用类型情况下表示是否引用相等,而“!=”操作符与“==”语义类似。 当然也有例外,System.String 类型则以“==”来处理值相等。因此,对于自定义值类型,如果重载 E quals 方法,则应该保持和“==”在语义上的一致,以返回值相等结果;而对于引用类型,如果以覆 写来处理值相等规则时,则不应该再重载“==”运行符号,因为保持其缺省语义为判断引用相等才 是恰当的处理规则。

      Equals 虚方法与==操作符的主要区别在于多态表现:Equals 通过虚方法覆写来实现,而==操 作符则是通过运算符重载来实现,覆写和重载的区别请参考 1.4 节“多态的艺术”。

  • 相关阅读:
    LeetCode 42. Trapping Rain Water
    LeetCode 209. Minimum Size Subarray Sum
    LeetCode 50. Pow(x, n)
    LeetCode 80. Remove Duplicates from Sorted Array II
    Window10 激活
    Premiere 关键帧缩放
    AE 「酷酷的藤」特效字幕制作方法
    51Talk第一天 培训系列1
    Premiere 视频转场
    Premiere 暴徒生活Thug Life
  • 原文地址:https://www.cnblogs.com/kikyoqiang/p/10347669.html
Copyright © 2011-2022 走看看