zoukankan      html  css  js  c++  java
  • ==、object.Equals()、object.ReferenceEquals()

     参考:http://www.cnblogs.com/pursue/articles/1614285.html

     

    有时必须比较两个值是否相等。 在某些情况下,您测试的是“值相等性”(也称为“等效性”),意即两个变量包含的值相等。 而在其他情况下,则必须确定两个变量是否引用内存中的同一基础对象。 这种类型的相等性称为“引用相等性”(或“标识”)。

     

    1.Object.ReferenceEquals(object objA,object objB)

    作用:比较两个引用类型的对象是否是对同一对象的引用,即引用相等性。

    (1)先检查objA、objB是否为null,如果仅有一个为null,返回false,如果两个均为null,返回true

    (2)如果 objA、objB为值类型,则先进行装箱到不同的对象实例,因此对于两个值类型,无论它们的值是否相等,总返回false;

    (3)如果  objA、objB均为字符串,比较的也是字符串的引用,与值无关。但由于c#字符串池的机制使得字符串的比较有些特殊,见下面的补充部分。

    补充:

     对多个引用赋值同一个字符串对象,CLR的解决方法更加巧妙。在默认情况下CLR会使用字符串池的机制,CLR启动的时候,在内部创建一个容器,它以键值对的形式存在,键值是字符串对象内容,值是字符串在托管堆上的引用,当一个新的字符串对象创建的时候CLR检查在这些值中是否已经存在这个字符串对象,如果已经存在就返回对应的值,也就是在托管堆中的引用,如果不存在就在这个容器中中开辟空间存放这个字符串,返回在他的引用。
          这里还是用一段代码来说明:
      public void StringPoolTest()
      {
       string str1 = "789";
       string str2 = "789";
       Console.WriteLine(Object.ReferenceEquals(str1 , str2));
       string str3 = "7" + "8" + "9";
       Console.WriteLine(Object.ReferenceEquals(str1, str3));
       char[] chars = new char[] { '7', '8', '9' };
       string str4 = new string(chars);
       Console.WriteLine(object.ReferenceEquals(str1 , str4));
      }
    输出结果:

    前两次都输出true说明str1和str2都指向同一个堆引用,最后一个输出false是因为它使用new关键字进行内存分配,字符串池机制不起作用。
    这里注意string str3 = "7" + "8" + "9";这个语句在正常的情况下只分配了一次内存,这个也是CLR的优化,在这里就没有分配内存了,因为str1这里已经分配好了。

    2.object.Equals(object objA,object objB)

    作用:比较任意两个CTS对象。

    (1)Equals方法对于值类型和引用类型的定义不同,对于值类型,类型相同,并且数值相同(对于struct的每个成员都必须相同)(即按位相等性,二进制表示形式),则Equals()返回 true,否则返回false;而对于非字符串的引用类型,默认的行为与ReferenceEquals()的行为相同,仅有两个对象指向同一个引用时才返回true;但对于string这个特殊的引用类型来说, Equals 比较的是字符串的值,而非引用,见下面

      输出:

    (2)Equals有静态方法和可重写的实例方法两个版本,如果类型的Equals()方法被重写,则调用重写方法,否则调用基类Object的Equals()实例方法。

    (3)值得注意的是,如果objA、objB为值类型(测试代码如图1所示),可以看出EqualsReferenceEquals方法一样均先对objA、 objB进行了装箱(IL代码如图2所示),但返回结果却不同,返回结果如图3所示。(原因是Equals方法用于值类型比较时,比较的是值类型的比特值,即按位相等性

    图1

    图2

    图3

     

     

    3.==

    ==是一个可以重载的二元操作符,可以用于比较两个对象是否相等。 
    (1)对于内置值类型,==判断的是两个对象的代数值是否相等。它会根据需要自动进行必要的类型转换,并根据两个对象的值是否相等返回true或者false。例如:

    Int a = 100; 
    Double b =100;

    If(a == b) 
    Console.WriteLine(“equal supports compare between different types!”);

    上面这段程序将会输出: 
    equal supports compare between different types!

     注意:由于二进制计算机上浮点算法的不精确性,因此浮点值(doublefloat)的相等比较会出现问题。

     

    (2)而对于用户定义的值类型,如果没有重载==操作符,==将是不能够使用的。例如: 
    Struct Userstruct1; 
    Userstruct1 a; 
    Userstruct1 b;

    If(a == b) 
    Console.WriteLine(“can == reach this far?”)

    上面的这段代码是不能够通过编译的。可以通过重载使==作用于用户定义的值类型。

     

    (3)对于非字符串的引用类型,== 默认的行为与Equals,ReferenceEquals的行为相同,仅有两个对象指向同一个Reference的时候才返回true。但是.NET Framework中的类很多对==进行了重载,例如String类的==与的行为相同,判断两个字符串的内容是否相等。所以在应用中,对于系统定义的引用类型建议不要使用==操作符,以免程序出现与预期不同的运行结果。

     (4)对于字符串类型来说,== 默认的行为与Equals的行为相同,比较的是字符串的值。

    4.比较对象的GetType()和typeof()时,使用==、Object.Equals()和 Object.ReferenceEquals()均可以。

      

  • 相关阅读:
    负载均衡算法
    .NET Core 如何上传文件及处理大文件上传
    ado.net 批量添加 更新 删除
    asp.net mvc session锁问题
    C# Cache 设定过期时间的方法
    C# 开源项目
    Linux上 发布.Net Core
    Roslyn
    .net core 基础知识
    神经网络基础
  • 原文地址:https://www.cnblogs.com/2008freestyle/p/2465059.html
Copyright © 2011-2022 走看看