[英]C# ValueType equals not comparing properties?
The following prints equals: 以下打印等于:
struct A
{
int x;
public A(int _x) { x = _x; }
public int Y
{
get
{
Random r = new Random();
return r.Next(0, 1000);
}
}
}
static void Main(string[] args)
{
A a1 = new A(1),a2 = new A(1);
if (a1.Equals(a2))
{
Console.Write("Equals");
}
else
{
Console.Write("Different");
}
}
Is there anyway to get C# to return false in that case? 无论如何,在这种情况下,是否会使C#返回false? Meaning, to take the properties under consideration when comparing value types?
意思是,在比较值类型时要考虑属性?
Write equal then hit "tab" button twice: 写相等,然后按两次“制表符”按钮:
// override object.Equals
public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
{
return false;
}
// TODO: write your implementation of Equals() here
throw new NotImplementedException();
return base.Equals(obj);
}
This is an automatically generated snippet. 这是一个自动生成的代码段。 Now you can try something like:
现在,您可以尝试以下操作:
// override object.Equals
public override bool Equals(object obj)
{
// checks for A versus A
if (obj == null || GetType() != obj.GetType())
{
return false;
}
// TODO: write your implementation of Equals() here
throw new NotImplementedException();
int compareThis=(A)obj.x;
return ((A)base).x==compareThis; // maybe casting is not needed
}
The recommended approach is to use IEquatable<T>
instead of using the default inherited Equals
method. 推荐的方法是使用
IEquatable<T>
而不是使用默认的继承的Equals
方法。 The IEquatable generic interface defines a generalized method that a value type or class implements to create a type-specific method for determining equality of instances. IEquatable通用接口定义了通用方法,值类型或类实现该通用方法以创建用于确定实例相等性的特定于类型的方法。
using System;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
A a1 = new A(1), a2 = new A(1);
//here the CLR will do a lot of unboxing and check operations via reflection in order to make a comparaison between fields value.
//just take a look bellow at the decompiled default Equals method how it's done
if (a1.Equals(a2))
{
Console.Write("Equals");
}
else
{
Console.Write("Different");
}
}
}
public struct A : IEquatable<A>
{
int x;
public A(int _x) { x = _x; }
public int Y
{
get
{
Random r = new Random();
return r.Next(0, 1000);
}
}
//here no boxing or unboxing is needed even if is a value type and the CLR will call this method first
public bool Equals(A other)
{
return this.Y == other.Y;
}
public override bool Equals(object obj)
{
//this is why a bad approach to compare both objects you need to unbox the struct arguments wich hurting performance
return this.Y == ((A)obj).Y;
}
public override int GetHashCode()
{
return base.GetHashCode();
}
//default implementation
//public override bool Equals(object obj)
//{
// return base.Equals(obj);
//}
}
}
CLR Implementation CLR实施
The CLR what's going underneath CLR到底发生了什么
public override bool Equals(object obj)
{
if (obj == null)
return false;
RuntimeType runtimeType = (RuntimeType) this.GetType();
if ((RuntimeType) obj.GetType() != runtimeType)
return false;
object a = (object) this;
if (ValueType.CanCompareBits((object) this))
return ValueType.FastEqualsCheck(a, obj);
FieldInfo[] fields = runtimeType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
for (int index = 0; index < fields.Length; ++index)
{
object obj1 = ((RtFieldInfo) fields[index]).UnsafeGetValue(a);
object obj2 = ((RtFieldInfo) fields[index]).UnsafeGetValue(obj);
if (obj1 == null)
{
if (obj2 != null)
return false;
}
else if (!obj1.Equals(obj2))
return false;
}
return true;
}
This is very similar to this question. 这与这个问题非常相似。
All you need to do is to override the Equals
method: 您需要做的就是重写
Equals
方法:
struct A
{
int x;
public A(int _x) { x = _x; }
public int Y
{
get
{
Random r = new Random();
return r.Next(0, 1000);
}
}
public override bool Equals(object obj)
{
//compare whatever you want...
}
}
}
覆盖equal方法,并根据属性比较返回true或false。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.