C#中的值类型和引用类型在相等性的判定上是不同的
以Object.Equal方法为例,值类型判定的是值相等(及所有成员相等,会在成员上调用递归调用Equal方法);而引用类型默认则是判断引用相等(及两个变量指向托管堆中的同一个对象)
先列出值类型基类(ValueType)重写的Equal代码(其中有两个重要的函数有[MethodImpl(MethodImplOptions.InternalCall), SecuritySafeCritical]属性,用Reflector看不到代码,还望大牛指点)
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;
}
引用类型重写Equal方法即能判断值相等性;
==运算符默认判断引用相等,也可重写(重写==,必须同时重写!=);
class TestB
{
public Int32 i;
public Single s;
public override bool Equals(object obj)
{
TestB other = obj as TestB;
if (other == null)
{
return false;
}
return (i == ((TestB)obj).i && s == ((TestB)obj).s);
}
public static bool operator ==(TestB lhs, TestB rhs)
{
return lhs.Equals(rhs);
}
public static bool operator !=(TestB lhs, TestB rhs)
{
// return lhs.Equals(rhs);
return !(lhs == rhs);
}
}
Object.ReferenceEqual静态方法则只能判断引用相等