《Effective C#》:区别四个判等函数
点击次数:25 次 发布日期:2008-11-27 00:19:10 作者:源代码网
|
源代码网推荐 源代码网推荐 首先要说的是Object.ReferenceEquals和Object.Equals这两个静态函数,对于它们俩来说,是不需要进行重写的,因为它们已经完成它们所要得做的操作。 源代码网推荐 源代码网推荐 对于Object.ReferenceEquals这个静态函数,函数形势如下: 源代码网推荐 源代码网推荐 public static bool ReferenceEquals( object left, object right ); 源代码网推荐 这个函数就是判断两个引用类型对象是否指向同一个地址。有此说明后,就确定了它的使用范围,即只能对于引用类型操作。那么对于任何值类型数据操作,即使是与自身的判别,都会返回false。这主要因为在调用此函数的时候,值类型数据要进行装箱操作,也就是对于如下的形式来说。 源代码网推荐 源代码网推荐 int n = 10; 源代码网推荐 源代码网推荐Object.ReferenceEquals( n, n ); 源代码网推荐 这是因为对于n这个数据装箱两次,而每次装箱后的地址有不同,而造成Object.ReferenceEquals( n, n )的结果永远为false。 源代码网推荐 源代码网推荐 对于第一个判等函数来说,没有什么好扩展的,因为本身已经很好地完成了它所要做的。 源代码网推荐 源代码网推荐 对于第二个Object.Equals这个静态函数,其形式如下: 源代码网推荐 源代码网推荐 public static bool Equals( object left, object right ); 源代码网推荐 按照书中对它的分析,其大致函数代码如下: 源代码网推荐 源代码网推荐 public static void Equals( object left, object right ) 源代码网推荐{ 源代码网推荐 // Check object identity 源代码网推荐 if( left == right ) 源代码网推荐 return true; 源代码网推荐 源代码网推荐 // both null references handled above 源代码网推荐 if( ( left == null ) || ( right == null ) ) 源代码网推荐 return false; 源代码网推荐 return left.Equals( right ); 源代码网推荐} 源代码网推荐 可以说,Object.Equals这个函数完成判等操作,需要经过三个步骤,第一步是需要根据对象所属类型的==操作符的执行结果;第二步是判别是否为null,也是和第一步一样,需要根据类型的==操作符的执行结果;最后一步要使用到类型的Equals函数的执行结果。也就是说这个静态函数的返回结果,要取决于后面要提到的两个判等函数。类型是否提供相应的判等函数,成为这个函数返回结果的重要因素。 源代码网推荐 源代码网推荐 那么对于Object.Equals这个静态方法来说,虽说接受参数的类型也属于引用类型,但是div class=code>int n = 10; 源代码网推荐 源代码网推荐Debug.WriteLine( string.Format( "{0}", Object.Equals( n, n ) ) ); 源代码网推荐 源代码网推荐Debug.WriteLine( string.Format( "{0}", Object.Equals( n, 10 ) ) ); 源代码网推荐 这是因为在此函数中要用到具体类型的两个判等函数,不过就函数本身而言,该做的判断都做了,因此不需要去重载添加复杂的操作。 源代码网推荐 源代码网推荐 为了更好的述说剩下两个函数,先解释一下等价的意义。对于等价的意义,就是自反、对称以及传递。 源代码网推荐 源代码网推荐 所谓自反,即a == a; 源代码网推荐 源代码网推荐 而对称,是a == b,则b == a; 源代码网推荐 源代码网推荐 传递是 a == b,b == c,则 a == c; 源代码网推荐 源代码网推荐 理解等价的意义后,那么在实现类型的判等函数也要满足这个等价规则。 源代码网推荐 源代码网推荐 对于可以重载的两个判等函数,首先来介绍的是类型的Equals函数,其大致形式如下: 源代码网推荐 源代码网推荐 public override bool Equals( object right ); 源代码网推荐 那么对于一个类型的Equals要做些什么操作呢,一般来说大致如下: 源代码网推荐 源代码网推荐 public class KeyData 源代码网推荐{ 源代码网推荐 private int nData; 源代码网推荐 public int Data 源代码网推荐 { 源代码网推荐 get{ return nData;} 源代码网推荐 set{ nData = value; } 源代码网推荐 } 源代码网推荐 源代码网推荐 public override bool Equals( object right ) 源代码网推荐 { 源代码网推荐 //Check null 源代码网推荐 if( right == null ) 源代码网推荐 return false; 源代码网推荐 源代码网推荐 //check reference equality 源代码网推荐 if( object.ReferenceEquals( this, right ) ) 源代码网推荐 return true; 源代码网推荐 源代码网推荐 //check type 源代码网推荐 if( this.GetType() != right.GetType() ) 源代码网推荐 return false; 源代码网推荐 源代码网推荐 //convert to current type 源代码网推荐 KeyData rightASKeyData = right as KeyData; 源代码网推荐 源代码网推荐 //check members value 源代码网推荐 return this.Data == rightASKeyData.Data; 源代码网推荐 } 源代码网推荐} 源代码网推荐 如上增加了一个类型检查,即 源代码网推荐 源代码网推荐 if( this.GetType() != right.GetType() ) |
源代码网推荐 这部分,这是由于子类对象可以通过as转化成基类对象,从而造成不同类型对象可以进行判等操作,违反了等价关系。
源代码网推荐
源代码网推荐 除此外对于类型的Equals函数来,其实并没有限制类型非要属于引用类型,对于值类型也是可以重载此函数,但是我并不推荐,主要是Equals函数的参数类型是不可变的,也就是说通过此方法,值类型要经过装箱操作,而这是比较影响效率的。
源代码网推荐
源代码网推荐 而对于值类型来说,我推荐使用最后一种判等函数,即重载运算符==函数,其大致形式如下:
源代码网推荐
源代码网推荐
public static bool operator == ( KeyData left, KeyData right );
源代码网推荐 对于一个值类型而言,其的大致形式应该如下:
源代码网推荐
源代码网推荐
源代码网推荐 对于一个值类型而言,其的大致形式应该如下:
源代码网推荐
源代码网推荐
public struct KeyData
源代码网推荐{
源代码网推荐 private int nData;
源代码网推荐 public int Data
源代码网推荐 {
源代码网推荐 get{ return nData;}
源代码网推荐 set{ nData = value; }
源代码网推荐 }
源代码网推荐 public static bool operator == ( KeyData left, KeyData right )
源代码网推荐 {
源代码网推荐 return left.Data == right.Data;
源代码网推荐 }
源代码网推荐 public static bool operator != ( KeyData left, KeyData right )
源代码网推荐 {
源代码网推荐 return left.Data != right.Data;
源代码网推荐 }
源代码网推荐}
源代码网推荐
源代码网推荐 由于==操作与!=操作要同步定义,所以在定义==重载函数的时候,也要定义!=重载函数。这也是.Net在判等操作保持一致性。那么对于最后一个判等函数,这种重载运算符的方法并不适合引用类型。这就是.Net经常现象,去判断两个引用类型,不要用==,而要用某个对象的Equals函数。所以在编写自己类型的时候,要保留这种风格。
源代码网推荐
源代码网推荐 那么对于以上介绍的四种判等函数,会产生如下类似的对比表格。
源代码网推荐
源代码网推荐
源代码网推荐 那么在编写类型判等函数的时候,要注意些什么呢,给出如下几点建议。
源代码网推荐
源代码网推荐 首先,要判断当前定义的类型是否具有判等的意义;
源代码网推荐
源代码网推荐 其次,定义类型的判等函数要满足等价规则;
源代码网推荐
源代码网推荐 最后一点,值类型最好不要重载定义Equals函数,而引用类型最好不要重载定义==操作符。
源代码网供稿.
源代码网推荐{
源代码网推荐 private int nData;
源代码网推荐 public int Data
源代码网推荐 {
源代码网推荐 get{ return nData;}
源代码网推荐 set{ nData = value; }
源代码网推荐 }
源代码网推荐 public static bool operator == ( KeyData left, KeyData right )
源代码网推荐 {
源代码网推荐 return left.Data == right.Data;
源代码网推荐 }
源代码网推荐 public static bool operator != ( KeyData left, KeyData right )
源代码网推荐 {
源代码网推荐 return left.Data != right.Data;
源代码网推荐 }
源代码网推荐}
源代码网推荐
源代码网推荐 由于==操作与!=操作要同步定义,所以在定义==重载函数的时候,也要定义!=重载函数。这也是.Net在判等操作保持一致性。那么对于最后一个判等函数,这种重载运算符的方法并不适合引用类型。这就是.Net经常现象,去判断两个引用类型,不要用==,而要用某个对象的Equals函数。所以在编写自己类型的时候,要保留这种风格。
源代码网推荐
源代码网推荐 那么对于以上介绍的四种判等函数,会产生如下类似的对比表格。
源代码网推荐
源代码网推荐
| 操作结果取决于 | 适用范围 | 建议 | |
| Object.ReferenceEquals | 两个参数对象是否属于同一个引用 | 引用类型 | 不要用它来判断值类型数据 |
| Object.Equals | 参数类型自身的判等函数 | 无限制 | 考虑装箱操作对值类型数据产生的影响 |
| 类型的Equals | 类型重载函数 | 无限制 | 考虑装箱操作对值类型数据产生的影响 |
| 类型的==重载 | 类型重载函数 | 无限制 | 不要在引用类型中重载此运算符 |
源代码网推荐 那么在编写类型判等函数的时候,要注意些什么呢,给出如下几点建议。
源代码网推荐
源代码网推荐 首先,要判断当前定义的类型是否具有判等的意义;
源代码网推荐
源代码网推荐 其次,定义类型的判等函数要满足等价规则;
源代码网推荐
源代码网推荐 最后一点,值类型最好不要重载定义Equals函数,而引用类型最好不要重载定义==操作符。
源代码网供稿.
上一篇: 飞鸟动画效果的制作方法 下一篇: [PS技巧十四]创建富有个性的双色图
《Effective C#》:区别四个判等函数的相关新闻
- asp如何获取数据库中所有表名和字段名称呢
- 教大家ASP Serv-u 来实现FTP的代码
- asp如何利用dictionary创建二维数组
- 教大家一个适合所有表的添加、删除、修改的函数
- asp的fso函数实现整个文件夹内容的复制到另一个文件夹
- 用ASP函数取出HTML里面的所有图片地址
- asp也可使用模板,实现ASP代码与页面的分离
- asp利用正则表达式去掉字符串中所有html内容
- asp函数之网站通过限制请求防止被采集
- 如何使用asp去掉字符串中的超链接呢
- asp函数之图片采集并且本地重命名保存
- 教大家有效提高asp页面的访问速度
- asp函数之操作excel文件
- ASP采集函数之获取网页内所需的html代码
- ASP函数之自动获取当前页面URL
- asp函数之检测conn.execute是否执行成功
- ASP也可以自动清空IE缓存里的内容
- asp函数之将内容生成word文档
