以下打印件等于:
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");
}
}
在这种情况下,有没有让C#返回false?意思是,在比较值类型时采用所考虑的属性?
答案 0 :(得分:3)
写入相等然后点击“tab”按钮两次:
// 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);
}
这是一个自动生成的代码段。现在你可以尝试类似的东西:
// 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
}
答案 1 :(得分:1)
建议的方法是使用IEquatable<T>
而不是使用默认的继承Equals
方法。 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实施
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;
}
答案 2 :(得分:0)
这与this问题非常相似
您需要做的就是覆盖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...
}
}
}
答案 3 :(得分:0)
覆盖等于方法并根据属性比较返回true或false。