zoukankan      html  css  js  c++  java
  • .net 中的相等性比较

    引用相等性和值相等性

    在 C# 中,相等性分为引用相等性值相等性。引用相等性是指,若两个引用类型的变量引用的是同一个对象,则它们具有引用相等性。
    // x, y, z 都是引用类型变量
    object x = new object();
    object y = new object();
    object z = x;
    
    // 输出 false,x 和 y 不具有引用相等性
    Console.WriteLine(object.ReferenceEquals(x, y));
     
    // 输出 true,x 和 z 具有引用相等性
    Console.WriteLine(object.ReferenceEquals(x, z));
     
    // 输出 true,x 和自身具有引用相等性
    Console.WriteLine(object.ReferenceEquals(x, x));
    值相等性是指,若两个变量----可以是引用类型或值类型----包含语义上相同的值,则它们具有值相等性。
    int i = 5;
    int j = 6;
    int k = 5;
    
    // 输出 false,i 和 j 不具有值相等性
    Console.WriteLine(i.Equals(j));
    
    // 输出 true,i 和 k 具有值相等性
    Console.WriteLine(i.Equals(k));
    
    // 输出 true,i 和自身具有值相等性
    Console.WriteLine(i.Equals(i));

    == 和 != 操作符

    == 操作符用于判断两个变量是否相等,默认的实现是:
    • 对于字符串以外的引用类型,判断变量是否具有引用相等性
    • 对于值类型,判断变量是否具有值相等性
    • 对于字符串类型,判断变量是否具有值相等性
    != 操作符与 == 操作符含义相反 。
     
    C#允许重载 == 和 != 操作符。规则是,若要重载其中的一个,则必须重载另一个。
     

    Object.ReferenceEquals 静态方法

    Object.ReferenceEquals 静态方法用于判断引用相等性,它接受两个 object 类型的参数:
     
    int i = 5;
    
    // 输出 false,i 被装箱两次,是两个不同的对象,不具有引用相等性
    Console.WriteLine(object.ReferenceEquals(i, i));
    
    // 相当于:
    object x = i;
    object y = i;
    Console.WriteLine(object.ReferenceEquals(x, y));

    .net 框架的源码实现中,ReferenceEquals 方法使用 == 操作符进行判断:

    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
    [System.Runtime.Versioning.NonVersionable]
    public static bool ReferenceEquals (Object objA, Object objB) {
        return objA == objB;
    }

     代码参考:http://referencesource.microsoft.com/#mscorlib/system/object.cs,4d607d6d56a93c7e

    字符串相等性

    在 .net 中,字符串是引用类型,但 == 运算符和 Equals 方法都使用值相等性对字符串进行比较。默认的比较方式是区分大小写的,有时我们希望进行不区分大小写的比较。因此 String 类还有一个 Equals 方法的重载,允许指定如何对字符串进行相等性比较:

    public bool Equals(string value, StringComparison comparisonType)

    StringComparison 参数允许指定要使用的区域性、大小写和排序规则。

    字符串的例子提示相等性比较不是绝对的,两个相同的对象,可能在一个上下文中相等,而在另一个上下文中不相等。

    Object.Equals 实例方法

    Object.Equals 实例方法的签名是:
    public virtual bool Equals(Object obj)

    这是一个虚方法,具体行为取决于是否进行了重写。Object 中 Equals 方法的实现是,如果参数 obj 与当前对象是同一实例,则返回 true。

    ValueType 重写了 Equals 方法:若两个值类型变量的类型相同,并且所有实例字段相等,则它们具有值相等性。ValueType 中的 Equals 方法使用反射实现,对性能略有影响。对于自定义值类型,可考虑重写 Equals 方法避免反射带来的性能损失。

    Object.Equals 静态方法

    这是实用工具性质的方法,用于判断两个变量是否相等,方法签名是:

    public static bool Equals(Object objA, Object objB)
    它的实现代码如下:
    public static bool Equals(Object objA, Object objB)
    {
        if (objA == objB)
        {
            return true;
        }
        if (objA == null || objB == null)
        {
            return false;
        }
        return objA.Equals(objB);
    }
     
    分析:
    1,若两个变量引用相同的对象,或都为 null,则返回 true。
    2,若任意一个变量为 null,另一个不为 null,则返回 false。
    3,若两个变量都不为 null,并且不引用同一对象,那么返回 objA.Equals(objB) 的结果。
     

    重写 Object.Equals 实例方法

    重写 Object.Equals 实例方法时,应遵循以下规则:

    • 自反:x.Equals(x) 应返回 true
    • 对称:x.Equals(y) 和 y.Equals(x) 应具有相同的结果
    • 传递:如果 x.Equals(y) 为 true,并且 y.Equals(z) 为 true,那么 x.Equals(z) 应为 true
    • 稳定:如果 x 和 y 未修改,那么连续调用 x.Equals(y) 应具有相同的结果
    • 当实参为 null 时,应始终返回 null。
    • 若重写 Equals 方法,那么还应重写 GetHashCode 方法,并且,两个相等对象的 GetHashCode 方法应返回相同的值

    IEquatable<T> 泛型接口

    IEquatable<T> 定义类型特定的相等性比较方法,此接口只定义了一个方法,签名为:

    bool Equals(T other)

    此接口是从 .net 2.0 开始伴随泛型集合引入的。在泛型集合上调用 Contains、IndexOf、LastIndexOf 和 Remove 等方法时,将使用此接口进行相等性比较。根据 MSDN 的说明,任何可能存储在泛型集合中的类都应实现此接口。

    如果实现了 IEquatable 接口,还应重写 Object.Equals 实例方法和 Object.GetHashCode 方法。

    IEqualityComparer<T> 泛型接口和 EqualityComparer<T> 泛型类

    IEqualityComparer 声明了两个方法:

    bool Equals(T x, T y)
    int GetHashCode(T obj)

    此接口允许在泛型集合中跳过 T 本身的 Equals 和 GetHashCode 实现,如果向泛型集合提供了 IEqualityComparer<T> 的实例,那么集合将使用 IEqualityComparer<T> 的 Equals 和 GetHashCode 方法进行比较。

    EqualityComparer<T> 为 IEqualityComparer<T> 泛型接口的实现提供基类。EqualityComparer<T>.Default 属性返回默认的相等性比较器,IEquatable<T> 与泛型集合的配合实际上是在这里起作用的:

    • 若 T 实现了 IEquatable<T> 接口,则 EqualityComparer<T>.Default 使用 IEquatable<T> 接口进行相等性比较
    • 否则,EqualityComparer<T>.Default 使用 Object.Equals 进行相等性比较
     
     
  • 相关阅读:
    禅道的安装
    项目管理必看的几个网站
    禅道管理中的项目管理--组织进行任务分解
    Redis--Springboot使用
    Mapper.xml--配置map<String, List<String>>输入
    SpringBoot-Dubbo、Zk
    高并发--并发编程的三大辅助类
    笔试-2020年西山居Java笔试题(补上,一直忘记补上了)
    HttpWebRequest.GetRequestStream方法timeout【第3次操作时就超时】的原因及解决办法
    洛谷 P2613 【模板】有理数取余(高精度取余,逆元)
  • 原文地址:https://www.cnblogs.com/dongbeifeng/p/equality-comparing-in-dot-net.html
Copyright © 2011-2022 走看看