在学习.net(通过c#)时,我找到了5种方法来检查对象之间的相等性.
我的问题是:
Mat*_*ell 29
ReferenceEquals()方法.
这用于测试两个给定变量是否指向同一对象(符号引用).它实际上相当于((object)a) == ((object)b).如果覆盖比较运算符(==),则ReferenceEquals保持一种访问默认行为的方法.
但是,如果您正在处理值类型(例如结构),那么它将始终返回false.这是因为比较框中的每个值类型都是新对象,因此引用自然不会相等.
虚拟Equals()方法.(System.Object的)
这是在语义上比较两个对象(任何类型)的默认方式.每个班级都会根据他们的选择覆盖.默认情况下,它等效于CLR调用(InternalEquals),它基本上比较了内存引用.
注意,如果两个对象返回true,Equals()那么GetHashCode()每个对象必须相等.然而,如果两个对象的哈希码值等效(即,obj1.GetHashCode() == obj2.GetHashCode())这样做并不意味着Equals()是真实的.
您的类通常应该实现Equals并GetHashCode作为区分类实例的手段,并且==如果它是值类型,则必须实现它或运算符(理想情况下都是).
请注意,对于值类型,默认Equals行为是,ValueType.Equals()如果您查看Reflector(或阅读MSDN描述),则使用反射来比较两个值实例的成员.
静态Equals()方法.
这相当于将return ((objA == objB) || (((objA != null) && (objB != null)) && objA.Equals(objB)))每种类型转换Object为测试的位置.我的测试显示忽略了重载的比较运算符,但Equals如果对象不为null且不是相同的引用,则将使用您的方法.因此,a.Equals(b)不一定相等object.Equals(a, b)(对于((object)a) == ((object)b)a或b为空的情况).
IEquatable接口的Equals方法.
IEquatable提供了一种方法,可以专门处理与同一个类的实例的比较.说过你的Equals方法应该以同样的方式处理行为:
如果实现Equals,还应该覆盖Object.Equals(Object)和GetHashCode的基类实现,以便它们的行为与IEquatable.Equals方法的行为一致.
为了处理类的对象将存储在数组或通用集合对象中的可能性,实现IEquatable是一个好主意,以便可以轻松地识别和操作对象.
比较运算符==
默认情况下,比较运算符在两个对象都是同一引用时返回true.
它不推荐重写比较运算符除非你正在处理一个值类型(在这种情况下,建议,与沿着Equals法)或你通常会由值(例如比较一个不可变的引用类型string).总是同时实现!=(事实上,requires a matching operator '!=' to also be defined如果我不这样做,我会收到错误).
资源:
mve*_*rdo 27
1 - 引用等于检查两个引用类型变量(类,而不是结构)是否被引用到同一个内存地址.
2 - 虚拟Equals()方法检查两个对象是否相等.让我们说你有这个课程:
class TestClass{
public int Property1{get;set}
public int Property2{get;set}
public override bool Equals(object obj)
{
if (obj.GetType() != typeof(TestClass))
return false;
var convertedObj = (TestClass)obj;
return (convertedObj.Property1 == this.Property1 && convertedObj.Property2 == this.Property2);
}
}
Run Code Online (Sandbox Code Playgroud)
并从该类实例化2个对象:
var o1 = new TestClass{property1 = 1, property2 = 2}
var o2 = new TestClass{property1 = 1, property2 = 2}
Run Code Online (Sandbox Code Playgroud)
虽然这两个对象不是TestClass的同一个实例,但对o1.Equals(o2)的调用将返回true.
3 - 静态Equals方法用于在检查中存在空值时处理问题.想象一下,例如:
TestClass o1 = null;
var o2 = new TestClass{property1 = 1, property2 = 2}
Run Code Online (Sandbox Code Playgroud)
如果你试试这个:
o1.Equals(o2);
Run Code Online (Sandbox Code Playgroud)
你会得到一个NullReferenceException,因为o1指向什么都没有.要解决此问题,请执行以下操作:
的Object.Equals(O1,O2);
准备此方法以处理空引用.
4 - IEquatable接口由.Net提供,因此您不需要在Equals方法中进行强制转换.如果编译器发现您已在类中尝试检查相等性的类中实现了接口,则它将使该方法优先于Object.Equals(Object)覆盖.例如:
class TestClass : IEquatable<TestClass>
{
public int Property1 { get; set; }
public int Property2 { get; set; }
public override bool Equals(object obj)
{
if (obj.GetType() != typeof(TestClass))
return false;
var convertedObj = (TestClass)obj;
return (convertedObj.Property1 == this.Property1 && convertedObj.Property2 == this.Property2);
}
#region IEquatable<TestClass> Members
public bool Equals(TestClass other)
{
return (other.Property1 == this.Property1 && other.Property2 == this.Property2);
}
#endregion
}
Run Code Online (Sandbox Code Playgroud)
现在,如果我们这样做:
var o1 = new TestClass{property1 = 1, property2 = 2}
var o2 = new TestClass{property1 = 1, property2 = 2}
o1.Equals(o2);
Run Code Online (Sandbox Code Playgroud)
被调用的方法是Equals(TestClass),在Equals(Object)之前.
5 - ==运算符通常与ReferenceEquals相同,它检查两个变量是否指向同一个内存地址.问题是可以覆盖此运算符以执行其他类型的检查.例如,在字符串中,它检查两个不同的实例是否相同.
这是一个有用的链接,可以更好地理解.Net中的平等性: