抛出问题:
1 程序员A在某天Debug代码的时候发现了一个不可思议的问题:从服务端获取两次数据组装的对象 DataObj1,DataObj2,竟然出现 DataObj1 == DataObj2 返回true的情况,两个不同的实例,引用自然而然是不同的,为什么?
2 程序员B看到C#的Object中定义了一个 public staticbool ReferenceEquals(object objA, object objB) 静态方法,这个是不是多余的?如果Object A,B,我要比较引用不是很直接吗? A == B
解答时间
代码:Object a, b;
这里的a和b确实是对Object对象的引用,这一点是没有任何异议的
但是
a == b;
的具体含义不能绝对认为这个就是针对 a 和 b的引用比较,因为DotNet/C#支持操作符的重载,关键字是 operator
a == b 的具体含义依赖于 == 这个操作符的实现:
1)对于引用类型这个操作符的默认行为是 比较对象的引用
2)对于值类型这个操作符的默认行为是按照值进行比较
另外,在重载 == 或者 != 操作符一定需要明确的是一定需要一起重载,成对出现。
了解了上面的点,上面的问题就很好解决了:
1)相同类型的不同实例,其引用一定不同,但是使用 == 返回true,很显然,该类型重载了 == 和 !=,这个很好验证可以检查类型的实现即可。
2)当我们确实希望按照引用进行比较,那么调用 ReferrecneEquals 一定保证比较的实现是基于引用的,这样一来就看出这个方法的独特用处了。
后面附一个简单的重载实例:
using System; using System.Collections.Generic; using System.Linq; namespace EqualImplement { class SampleObject { private Int32 m_Age; private Int32 m_Count; public SampleObject( Int32 i_age, Int32 i_count ) { m_Age = i_age; m_Count = i_count; } private static bool IsNull( Object i_so ) { return ReferenceEquals(i_so, null); } public override bool Equals( Object i_obj ) { if (!IsNull(i_obj)) { return base.Equals(i_obj); } return Equals(i_obj as SampleObject); } private bool Equals( SampleObject i_obj ) { return (i_obj.Age == m_Age) && (i_obj.Count == m_Count); } public Int32 Age { get { return m_Age; } } public Int32 Count { get { return m_Count; } } public override int GetHashCode() { return m_Age.GetHashCode(); } public static bool operator ==( SampleObject i_so1, SampleObject i_so2 ) { if (!IsNull(i_so1)) { return i_so1.Equals(i_so2); } if (!IsNull(i_so2)) { return i_so2.Equals(i_so1); } return true; } public static bool operator !=( SampleObject i_so1, SampleObject i_so2 ) { if (!IsNull(i_so1)) { return (!i_so1.Equals(i_so2)); } if (!IsNull(i_so2)) { return (!i_so2.Equals(i_so1)); } return false; } } }
调用:
using System; using System.Collections.Generic; using System.Linq; namespace EqualImplement { class Program { static void Main(string[] args) { var so1 = new SampleObject(12, 14); var so2 = new SampleObject(12, 14); Console.WriteLine("so1 == so2 ?" + ((so1 == so2) ? "Y" : "N")); Console.WriteLine("so1 and so2 have the same referrence ? " + ReferenceEquals(so1, so2)); Console.ReadKey(); } } }
输出结果类似:
so1 == so2 ?Y
so1 and so2 have the same referrence ? False