什么时候应该使用==?什么时候应该使用Equals?(如何判断值相等还是引用相等。)

来源:互联网 发布:织梦cms会员注册 编辑:程序博客网 时间:2024/05/17 03:59

什么时候应该使用==?什么时候应该使用Equals?(如何判断值相等还是引用相等。)

String类型是值类型还是引用类型?

String类型复杂的值和引用特性(不可不读)。

 

 

 

什么时候应该使用==?什么时候应该使用Equals?(如何判断值相等还是引用相等。)

 

转载:

什么时候应该使用   ==?什么时候应该使用   Equals?(转   原作:Jon   Skeet)  
  Equals   方法只是在   System.Object   中定义的一个虚拟方法,它由任何选择执行该任务的类所重写。==   运算符是一个可由类重载的运算符,该类通常具有恒等行为。  
   
  对于未重载   ==   的引用类型,该运算符会比较两个引用类型是否引用同一对象,而这恰好是   System.Object   中的   Equals   实现所做的工作。  
   
  对于未重载   ==   的值类型,该运算符会比较这两个值是否"按位"相等,即是否这两个值中的每个字段都相等。当您对值类型调用   Equals   时,仍然会发生这一情况,但这一次,该实现是由   ValueType   提供的,并且使用反射进行比较,从而使比较速度比特定于类型的实现慢很多。  
   
  到此为止,二者是如此类似。二者之间的主要区别是多态。运算符被重载而不是被重写,这意味着除非编译器知道调用更为具体的版本,否则它只是调用恒等版本。为阐明这一点,请看下面这个示例:  
   
  using   System;  
  public   class   Test  
  {  
  static   void   Main()  
  {  
                  //   Create   two   equal   but   distinct   strings  
                  string   a   =   new   string(new   char[]   {'h',   'e',   'l',   'l',   'o'});  
                  string   b   =   new   string(new   char[]   {'h',   'e',   'l',   'l',   'o'});  
                  Console.WriteLine   (a==b);  
                  Console.WriteLine   (a.Equals(b));  
                  //   Now   let's   see   what   happens   with   the   same   tests   but  
                  //   with   variables   of   type   object  
                  object   c   =   a;  
                  object   d   =   b;  
                  Console.WriteLine   (c==d);  
                  Console.WriteLine   (c.Equals(d));  
          }  
  }  
   
  结果是:  
   
  True  
  True  
  False  
  True  
   
  第三行是   False,原因在于编译器不知道   c   和   d   的内容都是字符串引用,因而只能调用   ==   的非重载版本。因为它们是对不同字符串的引用,所以恒等运算符返回   False。  
   
  那么,应该如何区别使用这些运算符呢?我的准则是:对于几乎所有引用类型,当您希望测试相等性而不是引用一致性时,请使用   Equals。例外的情况是字符串   -   使用   ==   比较字符串确实会使事情简单得多,而且代码可读性更好,但是   您需要记住,该运算符的两端都必须是类型字符串表达式,才能使比较正常进行。  
   
  对于值类型,我通常使用   ==,因为除非值类型本身包含引用类型(这种情况极为罕见),否则是恒等还是相等的问题无关紧要。

 

string 是值类型还是引用类型?

1,string 是建立在堆上而不是栈上,是引用类型,但是string几乎可以看作是值类型了。因为string的“==”和Equals都被写成值是否相等而不是是否是同一引用。

2,string对象保存在堆上而不是堆栈上,是引用类型的,因而当把一个字符串变量赋给另一个字符串时,会得到对内存中同一个字符串的两个引用.然后,修改其中一个字符串,注意这会创建一个完全新的string对象,而另一个字符串没改变!

  1. using System; 
  2. using System.Collections.Generic; 
  3. using System.Text;
  4. namespace ConsoleApplication1
  5. {
  6.     class Program
  7.     {
  8.         static void Main(string[] args)
  9.         {
  10.             string s1 = "abc";
  11.             string s2=s1;
  12.             Console.WriteLine((object)s1==(object)s2);
  13.             s2 = "abcd";
  14.             Console.WriteLine((object)s1 == (object)s2);
  15.             Console.ReadLine();
  16.         }
  17.     }
  18. }

输出:

TRUE

FALSE

 

String类型复杂的值和引用特性(不可不读)。

 

  1. using System; 
  2. using System.Collections.Generic; 
  3. using System.Text;
  4. namespace ConsoleApplication1
  5. {
  6.     class Program
  7.     {
  8.         static void Main(string[] args)
  9.         {
  10.             string s1 = "abc";
  11.             string s2=s1;
  12.             Console.WriteLine((object)s1==(object)s2);//1
  13.             s1 = "abcd";
  14.             Console.WriteLine((object)s1 == (object)s2);//2
  15.             s2 = "abcd";
  16.             Console.WriteLine((object)s1 == (object)s2);//3
  17.             s1 += "e";
  18.             s2 += "e";
  19.             Console.WriteLine((object)s1 == (object)s2);//4
  20.             s2 = "abcde";
  21.             Console.WriteLine((object)s1 == (object)s2);//5
  22.             char[] c=new char[]{'a','b','c','d','e'};
  23.             s2 = new String(c);
  24.             Console.WriteLine((object)s1 == (object)s2);//6
  25.             Console.WriteLine(s1 == s2);//7
  26.             Console.ReadLine();
  27.         }
  28.     }
  29. }

输出:

True

False

True

False

False

False

True

分析:

1,说明=赋值是把S1的引用赋予了S2

2,一旦S1改变,S1就会创建并指向新的字符串空间,而S2还是指向原来的空间

3,(分析)可能跟JAVA类似,S2先搜索是否已经存在“abcd”字符串在字符串池,如果有,则指向该字符串,这样,S1和S2引用又相等了。

4,(分析)S1要进行+=操作,首先要新创建一个字符串"abcd",然后再加"e"。S2在原字符串上进行+=操作。所以S1和S2引用不相同。

5,(分析),按照步骤3的分析,应该发现存在"abcde"字符串,那么S1和S2应该使用同样的引用类型,但是结果确实False,说明对字符串进行了+=操作后,虽然值相同,但是已经不适应3.

6,S1使用new string构造的空间,和S2的空间不相同,因此引用不相同。

7,说明string的==被重写,用来判断值相同而不是引用相同了。

 

结论:如果不刨根问底,那么string类型是可以看作是值类型来使用的,虽然他是引用类型。这应该就是这么复杂的string类设计的目的。

 

 

原创粉丝点击