参见:http://topic.csdn.net/u/20090908/00/e64b8f60-0c91-44c0-a3dc-4387b8dfaa21.html---------------------------------Jeffrey Richter 的《Microsoft .NET 框架程序设计(修订版)》(李建忠译)第157-160页:
6.1.3 为值类型实现 Equals 方法第5章曾经说过,所有的值类型都继承自 System.ValueType。System.ValueType 重写了 System.Object 提供的 Equals 方法实现。System.ValueType.Equals 方法在内部首先使用反射机制(本书20章将予以探讨)来得到类型所有的实例字段(译注:尽管这样的 Equals 方法是在 ValueType 中实现的,但是反射机制本身可以保证它永远能够反射出实际类型--也就是继承自 ValueType 的值类型--中定义的所有字段,这里有一个“预知”的意思。当然这样的“预知”是有代价的),然后再比较它们是否相等。这种比较的过程效率很低,但却是一个所有的值类型都能继承的、相当不错的默认实现。至少,这样的做法意味着引用类型继承的 Equals 判断的是引用相等,而值类型继承的 Equals 判断的是值相等。对于没有显式重写 Equals 方法的值类型,ValueType 提供的实现将被继承。下面的代码展示了 System.ValueType.Equals 方法的内部实现。(代码略)虽然 ValueType 已经提供了一个相当好的 Equals 实现,并且也适用于我们定义的绝大多数值类型,但我们仍然应该提供自己的 Equals 实现。原因是我们自己的实现执行起来效率较高,并且可以避免额外的装箱操作。下面的代码展示了怎样为一个值类型实现 Equals 方法:(代码略)对于值类型,我们应该为它定义一个强类型版本的 Equals 方法,让其接受定义类型作为参数。这样做不仅可以提供类型安全,而且还可以避免额外的装箱操作。除此之外,我们也应该为 == 和 != 提供强类型的重载操作符。下面的代码演示了怎样判断两个值类型是否相等:(代码略)
6.1.3 为值类型实现 Equals 方法第5章曾经说过,所有的值类型都继承自 System.ValueType。System.ValueType 重写了 System.Object 提供的 Equals 方法实现。System.ValueType.Equals 方法在内部首先使用反射机制(本书20章将予以探讨)来得到类型所有的实例字段(译注:尽管这样的 Equals 方法是在 ValueType 中实现的,但是反射机制本身可以保证它永远能够反射出实际类型--也就是继承自 ValueType 的值类型--中定义的所有字段,这里有一个“预知”的意思。当然这样的“预知”是有代价的),然后再比较它们是否相等。这种比较的过程效率很低,但却是一个所有的值类型都能继承的、相当不错的默认实现。至少,这样的做法意味着引用类型继承的 Equals 判断的是引用相等,而值类型继承的 Equals 判断的是值相等。对于没有显式重写 Equals 方法的值类型,ValueType 提供的实现将被继承。下面的代码展示了 System.ValueType.Equals 方法的内部实现。(代码略)虽然 ValueType 已经提供了一个相当好的 Equals 实现,并且也适用于我们定义的绝大多数值类型,但我们仍然应该提供自己的 Equals 实现。原因是我们自己的实现执行起来效率较高,并且可以避免额外的装箱操作。下面的代码展示了怎样为一个值类型实现 Equals 方法:(代码略)对于值类型,我们应该为它定义一个强类型版本的 Equals 方法,让其接受定义类型作为参数。这样做不仅可以提供类型安全,而且还可以避免额外的装箱操作。除此之外,我们也应该为 == 和 != 提供强类型的重载操作符。下面的代码演示了怎样判断两个值类型是否相等:(代码略)
解决方案 »
- 一个关于datagridview的问题
- wpf中如何获取frame中的一个page?
- 有没有能显示多列的listbox或是其他能显示多列的表
- 很简单的奉上66分
- DevExpress.XtraGrid.GridControl 不能显示数据
- 100分请教WebRequest获取wap.baidu.com的源码
- C#中复制了一个控件,文件名类名也改了,但还是出现错误,郁闷了,大侠帮忙解决一下啊
- 关于DataGrid里删除记录问题
- 生成文件名的方法
- 我想开发一个软件,可以画很多框框和箭头,然后在框框里填图象和文字,然后可以保存起来,需要什么准备知识?界面要用哪些控件好?
- 如何将一个DataTable保存为一个独立的文件,可以方便数据读写。
- 一个关于 C# FtpWebRequest 微软自带的ftp类 的问题 谢谢各位老大给看下
operators for types that it considers primitives. For example, the C# compiler knows how to
compare Object, Boolean, Char, Int16, Uint16, Int32, Uint32, Int64, Uint64, Single,
Double, Decimal, and so on for equality. In addition, these types provide implementations of
Equals, so you can call this method as well as use operators.还是看原版好,应该翻译成:
编译器为内置类型实现了==和!=运算现在又有了个新的问题,为什么Decimal也算?!Decimal应该排除在外吧,这个是重载过的,难道也这样?!
另提示一下,代码也有可能过时,
同样说法也会改变,因为这些不是规范里的内容.public override bool Equals(Object obj)
{
if (obj == null) return false; else
{
Type type = GetType();
if (type != obj.GetType()) return false;
FieldInfo[] fields = type.GetFields(BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance);
int posn;
Object value1,value2;
for (posn = 0; posn < fields.Length; ++posn)
{
value1 = fields[posn].GetValue(this);
value2 = fields[posn].GetValue(obj);
if (value1 == null)
{
if (value2 != null) return false;
}
else if (value2 == null)
{
return false;
}
else if (!value1.Equals(value2))
{
return false;
}
}
return true;
}
}
http://topic.csdn.net/u/20090904/21/639bdc71-16e8-48e8-9528-04c0b985dfdc.html
还记得14楼关于struct类型hashcode的论述嘛.我验证了一下,发现也是错的.《Effective C#》第十章中关于结构类型hashcode的结论
值类型自带的GetHashCode是以其第一个成员的GetHashCode值作为其的返回值。 public override int GetHashCode()
{
FieldInfo[] fields = GetType().GetFields(BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance);
int posn;
Object value;
for (posn = 0; posn < fields.Length; ++posn)
{
value = fields[posn].GetValue(this);
if (value != null) return value.GetHashCode();
}
return GetType().GetHashCode();
}现在这个说也法也过时了,不信大家自己做个验证,这里我就不上代码了.
有的值类型都继承自 System.ValueType。System.ValueType 重写了 System.Object 提供的 Equals 方法实现。System.ValueType.Equals 方法在内部首先使用反射机制(本书20章将予以探讨)来得到类型所有的实例字段。的我猜测是:为了性能,也行有了新的做法.[1]不要盲从本书上的说教,要自己验证了才算数,更要注意一下论证的环境.(三段论)
[2]可能.net的版本在变,情况同样会改变,除非是C#语言规范中认定的内容.
第2版没有对应的章节,只在“5.5 对象相等性和身份标识”这一节中有这么一段:顺便提一句:System.ValueType(所有值类型的基类)重写了Object的Equals方法,并进行了正确的实现来执行相等性检查(而不是同一性检查)。在内部,ValueType的Equals是像这样实现的:
1.如果obj参数为null,就返回false。
2.如果this和obj参数引用不同类型的对象,就返回false。
3.针对类型定义的每个实例字段,都将this对象的值与obj对象中的值进行比较。如果有字段不等,就返回false。
4.返回true。ValueType的Equals方法不会调用Object的Equals方法。
在内部,ValueType的Equals方法使用反射技术来完成上面的步骤3。由于CLR的反射机制较慢,所以在定义自己的值类型时,应该重写Equals方法,并提供自己的实现,以便在用类型的实例进行值相等性比较时提高性能。
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
RuntimeType type = (RuntimeType) base.GetType();
RuntimeType type2 = (RuntimeType) obj.GetType();
if (type2 != type)
{
return false;
}
object a = this;
if (CanCompareBits(this))
{
return FastEqualsCheck(a, obj);
}
FieldInfo[] fields = type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
for (int i = 0; i < fields.Length; i++)
{
object obj3 = ((RtFieldInfo) fields[i]).InternalGetValue(a, false);
object obj4 = ((RtFieldInfo) fields[i]).InternalGetValue(obj, false);
if (obj3 == null)
{
if (obj4 != null)
{
return false;
}
}
else if (!obj3.Equals(obj4))
{
return false;
}
}
return true;
}