改善C#程序的157个建议(连载11)

发表于:2011-10-27 09:55

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:陆敏技    来源:51Testing软件测试网采编

  建议11:区别对待==和Equals

  在开始本建议之前,首先要明确概念“相等性”。CLR中将“相等性”分为两类:“值相等性”和“引用相等性”。如果用来比较的两个变量所包含的数值相等,那么将其定义为“值相等性”;如果比较的两个变量引用的是内存中的同一个对象,那么将其定义为“引用相等性”。

  无论是操作符“==”还是方法“Equals”,都倾向于表达这样一个原则:

  对于值类型,如果类型的值相等,就应该返回True。

  对于引用类型,如果类型指向同一个对象,则返回True。

  下面的代码输出所遵循的就是以上原则:

  1. static void ValueTypeOPEquals()  
  2. {  
  3.     int i = 1;  
  4.     int j = 1;  
  5.     //True  
  6.     Console.WriteLine(i == j);  
  7.     j = i;  
  8.     //True  
  9.     Console.WriteLine(i == j);  
  10. }  
  11. static void ReferenceTypeOPEquals()  
  12. {  
  13.     object a = 1;  
  14.     object b = 1;  
  15.     //False  
  16.     Console.WriteLine(a == b);  
  17.     b = a;  
  18.     //True  
  19.     Console.WriteLine(a == b);  
  20. }  
  21. static void ValueTypeEquals()  
  22. {  
  23.     int i = 1;  
  24.     int j = 1;  
  25.     //True  
  26.     Console.WriteLine(i.Equals(j));  
  27.     j = i;  
  28.     //True  
  29.     Console.WriteLine(i.Equals(j));  
  30. }  
  31.  static void ReferenceTypeEquals()  
  32. {  
  33.     object a = new Person("NB123");  
  34.     object b = new Person("NB123");  
  35.     //False  
  36.     Console.WriteLine(a.Equals(b));  
  37.     b = a;  
  38.     //True  
  39.     Console.WriteLine(a.Equals(b));  
  40. }

  但是,我们同时也要了解,无论是操作符“==”还是“Equals”方法都是可以被重载的。比如,对于string这样一个特殊的引用类型,微软觉得它的现实意义更接近于值类型,所以,在FCL中,string的比较被重载为针对“类型的值”的比较,而不是针对“引用本身”的比较。

  从设计上来说,很多自定义的类型(尤其是自定义的引用类型)会存在和string类型比较接近的情况。如例子中所举的类型Person,在现实生活中,如果两者的IDCode是相等的,我们就认为两者是同一个人,这个时候,就要重载Equals这个方法,代码如下所示:

  1. class Person  
  2. {  
  3.     public string IDCode { get; private set; }  
  4.     public Person(string idCode)  
  5.     {  
  6.         this.IDCode = idCode;  
  7.     }  
  8.     public override bool Equals(object obj)  
  9.     {  
  10.         return IDCode == (obj as Person).IDCode;  
  11.     }  
  12. }

  这时,再通过Equals去比较两个具有相同IDCode的Person对象的值,返回的就会是true,代码如下所示:

  1. object a = new Person("NB123");  
  2. object b = new Person("NB123");  
  3. //False  
  4. Console.WriteLine(a == b);  
  5. // True  
  6. Console.WriteLine(a.Equals(b));

  这里,再引出操作符“==”和“Equals”方法之间的一点区别。一般来说,对于引用类型,我们要定义“值相等性”,应该仅仅去重载Equals方法,同时让“==”表示“引用相等性”。

  注意 由于操作符“==”和“Equals”方法从语法实现上来说,都可以被重载为表示“值相等性”和“引用相等性”。所以,为了明确有一种方法肯定比较的是“引用相等性”,FCL中提供了Object. ReferenceEquals方法。该方法比较的是:两个示例是否是同一个示例。

相关链接:

改善C#程序的157个建议(连载1)

改善C#程序的157个建议(连载2)

改善C#程序的157个建议(连载3)

改善C#程序的157个建议(连载4)

改善C#程序的157个建议(连载5)

改善C#程序的157个建议(连载6)

改善C#程序的157个建议(连载7)

改善C#程序的157个建议(连载8)

改善C#程序的157个建议(连载9)

改善C#程序的157个建议(连载10)

《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号