简体   繁体   English

C#ValueType是否等于不比较属性?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM