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()均可以。

      

  • 相关阅读:
    【转】【SEE】基于SSE指令集的程序设计简介
    【转】【Asp.Net】asp.net服务器控件创建
    ControlTemplate in WPF ——ScrollBar
    ControlTemplate in WPF —— Menu
    ControlTemplate in WPF —— Expander
    ControlTemplate in WPF —— TreeView
    ControlTemplate in WPF —— ListBox
    ControlTemplate in WPF —— ComboBox
    ControlTemplate in WPF —— TextBox
    ControlTemplate in WPF —— RadioButton
  • 原文地址:https://www.cnblogs.com/2008freestyle/p/2465059.html
Copyright © 2011-2022 走看看