문제

어떻게 == 운영자는 C#에서 실제로 작동합니까? 클래스의 객체를 비교하는 데 사용된다면 , 그것은 모든 것을 일치 시키려고 노력할 것입니다 의 속성, 아니면 동일한 메모리 위치 (또는 다른 것)에 대한 포인터를 찾을 수 있습니까?

가상의 예를 만들어 봅시다. 트위터 API를 사용하는 응용 프로그램을 작성하고 있습니다. 트위터 클래스, 단일 트윗의 모든 속성이있는 클래스 : 텍스트, 발신자, 날짜 및 시간, 출처 등. 클래스 객체를 비교하려면 클래스 트위터 동등성을 위해서만 사용할 수 있습니까?

Tweet a, b;
if (a == b)
{
//do something...
}

그럴 것입니다 모든 속성의 동등성을 확인하십시오트위터 사이의 수업 그리고 ?

그렇지 않다면 올바른 접근 방식은 과부하가 될 것입니다 == 운영자 모든 필드의 동등성을 명시 적으로 확인하려면?

업데이트: 처음 두 가지 답변에서 다음과 같이 가정 할 때 제가 옳습니다.

  • 만약 == 운영자 또는 동등합니다 메소드는 클래스에 대해 과부하되지 않습니다 == 연산자 물체 클래스가 사용됩니다.
  • 그만큼 == 연산자 물체 메모리 위치의 평등을 수업 검사합니다.
  • 나는 과부하해야한다 == 연산자 또는 동등합니다 이 작업을 수행하는 방법.
  • 오버로드에서는 수동으로 속성의 동등성을 확인해야합니다. 반자동으로 반자동으로 할 수있는 방법이 없습니다., 오른쪽?

업데이트 #2 : Yuriy는 == 운영자 반사. 이 작업은 어떻게 할 수 있습니까? 샘플 코드 좀 주시겠습니까? 감사!

도움이 되었습니까?

해결책

MSDN은 좋은 것을 가지고 있습니다 예시 그것을하는 방법 :

   public override bool Equals(object o) 
   {
      try 
      {
         return (bool) (this == (DBBool) o);
      }
      catch 
      {
         return false;
      }
   }

그런 다음 ==와! = :

// Equality operator. Returns dbNull if either operand is dbNull, 
   // otherwise returns dbTrue or dbFalse:
   public static DBBool operator ==(DBBool x, DBBool y) 
   {
      if (x.value == 0 || y.value == 0) return dbNull;
      return x.value == y.value? dbTrue: dbFalse;
   }

   // Inequality operator. Returns dbNull if either operand is
   // dbNull, otherwise returns dbTrue or dbFalse:
   public static DBBool operator !=(DBBool x, DBBool y) 
   {
      if (x.value == 0 || y.value == 0) return dbNull;
      return x.value != y.value? dbTrue: dbFalse;
   }

그리고 gethash 방법을 과부하시키는 것을 잊지 마십시오.

편집하다:

비교에서 반사를 사용하기 위해 다음의 빠른 샘플을 썼습니다. 이것은 훨씬 더 포괄적이어야합니다. 사람들이 나를 원한다면 다음과 같은 블로그를 시도 할 수 있습니다.

public class TestEquals
{
    private int _x;
    public TestEquals(int x)
    {
        this._x = x;
    }

    public override bool Equals(object obj)
    {
        TestEquals te = (TestEquals)obj;
        if (te == null) return false;

        foreach (var field in typeof(TestEquals)
            .GetFields(BindingFlags.NonPublic | BindingFlags.Instance))
        {
            if (!field.GetValue(this).Equals(field.GetValue(te)))
                return false;
        }
        return true;
    }
}

다른 팁

참조 유형의 경우 두 가지의 기본 구현 == 운영자와 Equals() 메소드는 단순히 두 객체가 동일한 참조를 가지므로 동일한 인스턴스인지 확인합니다.

두 개의 다른 객체의 내용을 확인하려면 동일하다면 코드를 작성하여 직접 수행해야합니다. 반사와 관련이있을 것입니다 ( mbunit 테스트 프레임 워크는이 라인을 따라 무언가를합니다) 그러나 성능이 큰 페널티와 어쨌든 기대했던 일을 할 수 없을 가능성이 높으며 구현해야합니다. == 또는 Equals 그리고 GetHashCode 손으로.

적절한 접근법은 설명대로 == 연산자 외에 트윗 클래스의 평등 메소드를 과부하입니다. 여기.

이 트윗 클래스의 모든 속성의 동등성을 확인하여 A와 B 사이의 동등성을 확인합니까?

아니

그렇지 않은 경우, 올바른 접근 방식은 == 연산자에게 모든 필드의 동등성을 명시 적으로 점검하기 위해 과부하하는 것입니까?

과부하 할 수 있습니다 == 연산자 또는 과부하 동등합니다 기능.

편집하다

@yuriy는 모든 비 공개 변수를 컴파일하는 데 좋은 예를 제공했습니다. 예를 썼기 때문에 여기에 있습니다 (광산 비교 속성)

class TwitterItem
{
    private string myValue = "default value";
    public string Value1
    {
        get { return myValue; }
        set { myValue = value; }
    }
    public string Value2
    {
        get { return myValue; }
        set { myValue = value; }
    }
    public string Value3
    {
        get { return myValue; }
        set { myValue = value; }
    }

    public override bool Equals(object obj)
    {
        if (base.Equals(obj)) return true;

        Type type = typeof(TwitterItem);
        PropertyInfo[] properties = type.GetProperties();

        foreach (PropertyInfo property in properties)
        {
            if (false == property.GetValue(this, null).Equals(property.GetValue(obj, null)))
                return false;
        }

        return true;
    }
}

반사를 사용하여 속성을 비교할 수 있습니다.

var a = new Entity() { Name = "test", ID = "1" };
var b = new Entity() { Name = "test", ID = "1" };
var c = new Entity() { Name = "test", ID = "2" };
System.Diagnostics.Debug.WriteLine(a.Equals(b));//Returns true
System.Diagnostics.Debug.WriteLine(a.Equals(c));//Returns false


public class Entity
{
    public string Name { get; set; }
    public string ID { get; set; }
    public override bool Equals(object obj)
    {
        var t = obj.GetType();
        foreach (var p in t.GetProperties())
        {
            if (t.GetProperty(p.Name).GetValue(obj, null) != t.GetProperty(p.Name).GetValue(this, null))
                return false;
        }
        return true;
    }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top