문제

이는 최근에,지금까지 나는 행복하게 재정의 평등 사업자(== 다)및/또는 Equals 방법은 있는지 확인하기 위해 두 가지 유형을 참조로 포함된 동 데이터 (i.e두 개의 서로 다른 경우는 동일).

내가 이것을 사용하더라도 더 이네에 더하여 자동화된 테스트(비교 참조/예상되는 데이터에 대해 반환).

를 찾는 동안 몇 가지의 코딩 표준이 지침에 MSDN 를 건너 왔어 문서 는 것은 그것에 대하여 조언한다.지금 내가 이해 이 문서에서 말하는 이(기 때문에 그들이 동일하지 않은 인스턴스 다)하지만 그에 대한 답변을 제공하지 않습니다 질문:

  1. 는 가장 좋은 방법은 무엇입 비교 참조 두 종류?
  2. 우리가 구현 IComparable?(도 내가 보았는 예약해야에 대한 가치 유형 전용).
  3. 은 거기에 몇 가지 인터페이스지에 대해 알아?
  4. 우리는 단지 우리 자신이?!

많은 감사합니다^_^

업데이트

처럼 보이는 난 잘못 읽기의 어떤 문서는(그것은 긴 일)과 재정의 Equals 방법이 있을 수 있습니다..

을 구현하는 경우에는 참조 유형을 고려해야 합니다 재정의 Equals 방법에 참조하 유형 당신의 유형처럼 보이는 기본 형식 과 같은 지점,문자열,BigNumber, 그래서.대부분의 유형을 참조해야한 습니다. 평등 연산자 도 면 그들은 무시 Equals.그러나, 을 구현하는 경우 참조 입력하는 값 는 의미와 같은 복잡한 번호 형,재정의해야 하는 평등 연산자입니다.

도움이 되었습니까?

해결책

그것처럼 당신은 코딩에서는 C#는 방법이라고 같는 당신의 클래스를 구현해야 할 두 개체를 비교하여 몇 가지 다른 측정항목보다는"이러한 두 가지 포인터(기 때문에 객체를 처리하는 것,포인터)동일한 메모리 주소?".

저는 그 일부에서 샘플 코드 :

class TwoDPoint : System.Object
{
    public readonly int x, y;

    public TwoDPoint(int x, int y)  //constructor
    {
        this.x = x;
        this.y = y;
    }

    public override bool Equals(System.Object obj)
    {
        // If parameter is null return false.
        if (obj == null)
        {
            return false;
        }

        // If parameter cannot be cast to Point return false.
        TwoDPoint p = obj as TwoDPoint;
        if ((System.Object)p == null)
        {
            return false;
        }

        // Return true if the fields match:
        return (x == p.x) && (y == p.y);
    }

    public bool Equals(TwoDPoint p)
    {
        // If parameter is null return false:
        if ((object)p == null)
        {
            return false;
        }

        // Return true if the fields match:
        return (x == p.x) && (y == p.y);
    }

    public override int GetHashCode()
    {
        return x ^ y;
    }
}

Java 는 매우 유사한 메커니즘이 있습니다.이 equals() 방법의 일부입 클래스고의 클래스 오버로드하려는 경우 당신은 그것을 이 유형의 기능이 있습니다.

이유는 과부'=='나는 아이디어에 대한 개체는 일반적으로,당신은 여전히 할 수 있는"이러한 동일한 포인터를"비교할 수 있습니다.이들은 일반적으로 의존을 위해,예를 들어,삽입하는 요소가 목록으로는 어디 중복을 허용하며,일부 framework 물건으면 작동하지 않을 수 있으므로 이 연산자입니다 과부에서는 표준 이외의 방법입니다.

다른 팁

구현을 평등합니다.순대,효율적으로 코드없이 중복 은 어렵습니다.특히,참조에 대한 형태로 값을 의미한다(즉 불변의 종류는 치료 equvialence equality다),당신을 구현해야 System.IEquatable<T> 인터페이스, 및 구현해야 합니다 모든 다른 작업(Equals, GetHashCode==, !=).

예를 들어,여기에 클래스를 구현하는 값이 같:

class Point : IEquatable<Point> {
    public int X { get; }
    public int Y { get; }

    public Point(int x = 0, int y = 0) { X = x; Y = y; }

    public bool Equals(Point other) {
        if (other is null) return false;
        반 X.Equals(니다.X)&&Y.Equals(니다.Y);
    }

    public override bool Equals(object obj) => Equals(obj as Point);

    public static bool operator ==(Point lhs, Point rhs) => object.Equals(lhs, rhs);

    public static bool operator !=(Point lhs, Point rhs) => ! (lhs == rhs);

    public override int GetHashCode() => X.GetHashCode()^Y.GetHashCode();
}

만 움직일 수 있는 부분을 위 코드에서는 굵게 표시된 부품:두 번째 라인에서 Equals(Point other)GetHashCode() 방법입니다.다른 코드를 수정해서는 안 됩니다.

에 대한 참조하는 클래스를 나타내지 않 변경할 수 없는 값을 구현하지 않은 연산자 ==!=.대신,그들의 기본값을 의미하는 것입니다 비교 개체의 정체성입니다.

코드 동일시에도 물체의 파생 클래스는 유형입니다.종이 바람직하지 않기 때문에 평등 사이의 기본 클래스고 파생된 클래스 정의하지 않.불행하게도,.물 및 코딩 가이드라인은 매우 분명하지 않다 여기에.코드는 것---끝---이력서 만듭니다 게시 에서 또 다른 대답이, 이,취약 원치 않는 동작이기 때문에 Equals(object x)Equals(SecurableResourcePermission x) 이 경우 다릅니다.

기 위해서는 이를 변경하는 행동을 추가적인 유형을 확인에 삽입할 수 있는 강력한 형식 Equals 위의 방법:

public bool Equals(Point other) {
    if (other is null) return false;
    if (other.GetType() != GetType()) return false;
    반 X.Equals(니다.X)&&Y.Equals(니다.Y);
}

아래 나는 무엇을 표현할 때 당신이해야 할 구현 IEquatable 제공하는 정서의 다양한 MSDN 문서 페이지입니다.


요약

  • 테스트할 때 값이 같은 원하는대로(같은 사용할 때는 객체에서 컬렉션)를 구현해야 합니다 IEquatable 인터페이스를 재정의 개체입니다.Equals,그리고 GetHashCode 클래스입니다.
  • 테스트할 때 참조에 대한 평등은 원하는 사용해야 합니다==연산자,운영자!= 고 체입니다.ReferenceEquals.
  • 당신만을 재정의 연산자==및 운영자!= 대 ValueTypes 과 변경할 수 없는 참조 형식입니다.

IEquatable

이 시스템입니다.IEquatable 인터페이스입니다 비교하는 데 사용되는 두 개의 인스턴스의 개체에 대한 평등.객체를 기반으로 비교에 논리를 구현합니다.비교 결과를 나타내는 부울 값을 경우 객체가 다릅니다.이에 대비하는 시스템입니다.IComparable 인터페이스는 정수를 반환하는 방법을 나타내는 개체 값은 다릅니다.

이 IEquatable 인터페이스를 선언하는 두 가지 방법을 재정의해야.Equals 방법이 포함되어 구현을 수행하는 실제적인 비교 및 true 를 반환하는 경우 객체에 값이 같은지,또는 잘못된 경우 그들은하지 않습니다.GetHashCode 방법을 반환해야 합니다 독특한 해쉬값을 사용할 수 있는 고유하게 식별하는 동일한 개체를 포함하는 다른 값입니다.해싱 알고리즘의 유형을 사용은 구현별로 다릅니다.

IEquatable.Equals 방법

  • 을 구현해야 합 IEquatable 에 대한 개체를 처리할 가능성이 될 것이라는 배열에 저장된 또는 일반적인 컬렉션입니다.
  • 를 구현하는 경우 IEquatable 당신은 또한 재정의 기본 클래스를 구현합니다.Equals(Object)및 GetHashCode 도록 자신의 행동과 일치하는 IEquatable.Equals 방법

에 대한 지침을 재정의 Equals()연산자==(C#프로그래밍 가이드)

  • x.Equals(x)true 를 반환합니다.
  • x.Equals(y)같은 값을 반환합니다.Equals(x)
  • 는 경우(x.Equals(y)&&y.Equals(z))true 를 반환한 다음,x.Equals(z)true 를 반환합니다.
  • 계속 호출 x.Equals(y)같은 값을 반환하는 개체를 참조하 x 및 y 수정되지 않습니다.
  • x.Equals(null)false 를 반환합니다(예 null 이 아닌 값 형식만 있습니다.에 대한 더 많은 정보를 참조하십시오 러(C#프로그래밍 가이드).)
  • 의 새로운 구현을 같아야에 던지지 예외가 있습니다.
  • 권장하는 모든 클래스를 재정의하는 같음 또한 재정의 개체입니다.GetHashCode.
  • 는 추천을 구현하는 것 외에 Equals(object),모든 클래스를 구현 Equals(형식)에 대한 자신의 유형,성능을 개선할 수 있습니다.

기본적으로,연산자==에 대한 테스트를 참조하여 평등지 여부를 결정하는 두 가지 참조가 동일한 개체입니다. 따라서,참조하지 않을 구현해야 연산자==을 얻기 위해 이 기능이 있습니다.때 유형을 변경할 수 없는 데이터가 포함된 인스턴스에서 변경할 수 없습니다,오버로드 연산자==을 비교 값이 같은지 대신 평등한 참조할 수 있기 때문에 유용,로 변경할 수 없는 개체들이 동일한 만큼 그들은 동일한 값입니다. 그것은 좋은 아이디어를 재정의 연산자==에서 변경할 수 없는 형식입니다.

  • 오버로드 연산자==구현해야에 던지지 예외가 있습니다.
  • 모든 유형는 operator==도 과부하 운전자!=.

==Operator(C#참조)

  • 미리 정의된 가치 유형,평등 사업자(==)할 경우 true 를 반환 값의 피연산자는 같고,그렇지 않으면 false 입니다.
  • 참고를 위한 형식 이외의 문자열==true 를 반환합니다면 그 피연산자가 동일한 개체입니다.
  • 문자열을 입력,==값과 비교의 문자열입니다.
  • 테스트할 때 null 사용에 대한==비교 내 연산자==를 재정의해야 합를 사용하여 기본 개체 클래스 연산자입니다.지 않는 경우,무한 재귀이 발생한 결과에서 유래.

체입니다.Equals 방법(Object)

하는 경우 프로그래밍 언어를 지원하는 운영자 과부하는 경우 당신은 선택을 하중 초과 같음 운영자를 위해 지정된 형식,형식을 재정의해야 합니다 Equals 방법입니다.등의 구현을 같는 방법을 반환해야 합 같은 결과 같음 연산자

다음과 같은 지침을 구현하기 위한 값 유형:

  • 고려한 재정의 동일한 성능 향상을 통해 제공하는 기본값의 구현을 같음에 변환.
  • 를 재정의하는 경우 동일 언어로 지원하는 운영자 과부해야 합니다 하중 초과 평등에 대한 운영자의 가치 유형입니다.

다음과 같은 지침을 구현하기 위한 reference 유형:

  • 의 재정의를 고려 Equals 에 참조 형식을 경우 의미의 유형을 기반으로는 사실을 나타내는 어떤 값(s).
  • 대부분의 유형을 참조해 초기 평등을 운전자는 경우에도,그들은 무시 같습니다.그러나,구현하는 경우 참고 입력하는 값 의미를 갖는 등 복잡한 숫자 입력,재정의해야 합 같음 연산자입니다.

추가적인 문제점

는 문서에는 그냥 좋에 대해 재정의 평등 운전자(참조 형),지에 대해 재정의하 같습니다.당신이 우선되어야 한다 같 내체(참조하거나 값)는 경우에 평등을 확인합니다 뭔가 의미보다 더 많은 참조를 확인합니다.하려면 인터페이스를 구현할 수도 있습니다 IEquatable (사용하여 일반적인 컬렉션도 있습니다).를 구현하는 경우 IEquatable,그러나,당신은 또한 재정이 동등으로 IEquatable 섹션국:

를 구현하는 경우 IEquatable<T>에,당신은 또한 재정의 기본 클래스를 구현합니다.Equals(Object)및 GetHashCode 도록 자신의 행동과 일치하는 IEquatable<T>.Equals 방법입니다.를 재정의하는 경우 객체입니다.Equals(Object),의 재정의 구현을 정도라는 통화에서 정적 Equals(시스템입니다.체,시스템입니다.체)방법에서 당신의 클래스입니다.이렇게 하면 모든 호출 Equals 메서드의 일관된 결과를 반환.

에 관련하여 여부를 당신을 구현해야 같 및/또는 평등사를 진행하고 있습니다.

구현을 같음 방법

대부분의 유형을 참조하지 않아야 하중 초과 평등을 운전자는 경우에도,그들은 무시 같습니다.

에 대한 지침을 구현을 같음과 같음 연산자(==)

Override Equals 방법을 구현할 때마다 평등 사업자(==),그리고 그들이 동일한 것입니다.

이를 할 필요가 있다고 말한 재정의 Equals 을 구현할 때마다 평등을 연산자입니다.가 말해야 하는 재정의 평등은 운영자는 무시할 때 같습니다.

복잡한 물체 수율을 보시려 비교는 다음을 구현하 IComparable 및 정의하는 비교로서 비교한 방법으로 구현.

예를 들어 우리는"차량"개체의 유일한 차이점이 될 수 있습 등록번호하고 우리가 사용하는 이를 비교하는지 확인하는 예상되는 값에 반환되는 테스트는 우리가 원하는 것입니다.

내가 사용하는 경향이 무엇인---끝---이력서 자동적으로 만듭니다.예를 들어,그것은 autocreated 이 중 하나에 대한 내 reference 유형:

public override bool Equals(object obj)
{
    if (ReferenceEquals(null, obj)) return false;
    if (ReferenceEquals(this, obj)) return true;
    return obj.GetType() == typeof(SecurableResourcePermission) && Equals((SecurableResourcePermission)obj);
}

public bool Equals(SecurableResourcePermission obj)
{
    if (ReferenceEquals(null, obj)) return false;
    if (ReferenceEquals(this, obj)) return true;
    return obj.ResourceUid == ResourceUid && Equals(obj.ActionCode, ActionCode) && Equals(obj.AllowDeny, AllowDeny);
}

public override int GetHashCode()
{
    unchecked
    {
        int result = (int)ResourceUid;
        result = (result * 397) ^ (ActionCode != null ? ActionCode.GetHashCode() : 0);
        result = (result * 397) ^ AllowDeny.GetHashCode();
        return result;
    }
}

를 재정의하려는 경우 == 고 아직도 ref 검사를 계속 사용할 수 있습니다 Object.ReferenceEquals.

Microsoft 나타나 변경되었을 그들의 조정,또는 적어도가 충돌하는 정보에 대해 적시에 평등을 연산자입니다.에 따라 이 Microsoft 문서 제목하는 방법:정의 값이 같은지에 대한 유형:

"==및!= 연산자를 사용할 수 있습으로 수업하는 경우에도 클래스에 과부하가 걸리지 않습니다.그러나,기본 동작을 수행에 대한 참조 평등을 확인합니다.클래스에서는 경우에,당신은 하중 초과 같음 방법은,당신은 하중 초과==및!= 사업자,그러나 그것은 필요하지 않습니다."

에 따라 에릭 프라하에서 자신의 응답 질문에 대해 물어보았 최소한 코드에 대한 평등에서의 C# -그는 말합니다:

"위험으로 실행 여기서 당신을 얻을==운영자에 대해 정의된 당신은 참조가 같은 기본적으로 합니다.당신은 쉽게 끝까지 상황에서는 과부 같음 방법은 값이 같은지 및==지는 평등,그리고 당신은 실수로 사용 참조를 평등하지 않을 참조한 것은 가치 같습니다.이것은 오류가 발생하기 쉬운 실천하기 어려운 장소에 의해 인간의 코드를 검토합니다.

몇 년 전 나는 일에 정적 해석하는 알고리즘을 통계적으로 이 상황을 감지,그리고 우리는 결함이 발견율이에 대한 두 개의 인스턴스당 백만 라인의 코드 간에 모든 코드베이스는 우리가 공부한다.을 고려할 때만 지원했다가 어딘가에 재정의 Equals,불량률을 분명히 상당히 높다!

또한,비용을 고려하십시오 vs 위험이 있습니다.이미 있는 경우 구현 IComparable 다음 쓰는 모든 사업자는 사소한 하나-라이너는 없을 것이 버그가 되지 않을 것입니다 변경되었습니다.그것의 가장 저렴한 코드를 작성합니다.면 사이의 선택의 여지가 주어진 고정 비용을 작성하고 테스트하는 명의 작은 방법에 대한 결의 비용을 발견하고 수정하 보 버그를 참조 평등은 사용되는 대신 값이 같은지,저는 알고 있는 한 나는 것입니다."

니다.NET 프레임워크에 적용==나!= 모든 유형를 작성할 것입니다.하지만,위험은 무슨 일이 일어날 경우 다른 사람 않습니다.그래서,클래스의 경우 제 3 자에 대한 후,나는 항상을 제공합==및!= 연산자입니다.클래스의 경우에만 사용하기 위한 내부적으로 그룹에 의해 나는 여전히 아마 구현==및!= 연산자입니다.

나는 단지 구현 <, <=,>,그리고>=운영자는 경우 IComparable 을 구현했습니다.IComparable 해야만 구현될 경우 입력이 필요를 지원하는 주문과 같은 정렬할 때 또는 사용 중인 주문 일반 컨테이너 같은 SortedSet.

는 경우 그룹 또는 회사 정책을 지지하지 않 구현==및!= 운영자-후 나의 코스를 따라하는 정책입니다.는 경우 이러한 정책은 장소에 있었다,그것은 것이 현명 할 것이 그것을 적용 Q/A 코드를 분석 도구하는 플래그의 어떤 발생==및!= 사업자와 함께 사용할 경우 참조 형식입니다.

내가 믿고 무언가를 얻을 확인하는 것만 큼 간단체를 평등에 대한 정확한 까다로운 일이다.NET 의 디자인이다.

에 대한 구조체

1)구현 IEquatable<T>.그것은 성능 향상에 눈에 띄게.

2)당신이 당신의 자신의 Equals 지금,재정의 GetHashCode, 을 일관적으로 다양한 평등을 확인 재정의 object.Equals 뿐만 아니라.

3)오버로드 ==!= 운영될 필요가 없는 종교적으로 수행한 이후 컴파일러 경고하는 경우에 당신은 실수로 동일시는 구조체로 다른 ==!=, 지만,그렇게 좋은 것으로 일관 Equals 방법이 있습니다.

public struct Entity : IEquatable<Entity>
{
    public bool Equals(Entity other)
    {
        throw new NotImplementedException("Your equality check here...");
    }

    public override bool Equals(object obj)
    {
        if (obj == null || !(obj is Entity))
            return false;

        return Equals((Entity)obj);
    }

    public static bool operator ==(Entity e1, Entity e2)
    {
        return e1.Equals(e2);
    }

    public static bool operator !=(Entity e1, Entity e2)
    {
        return !(e1 == e2);
    }

    public override int GetHashCode()
    {
        throw new NotImplementedException("Your lightweight hashing algorithm, consistent with Equals method, here...");
    }
}

클래스

MS:

대부분의 유형을 참조하지 않아야 하중 초과 평등을 운전자는 경우에도,그들은 무시 같습니다.

== 같은 느낌 값이 같은지,더 많은 다음과 같은 문법을 위한 Equals 방법입니다.쓰 a == b 은 많은 것보다 더 직관적 작성 a.Equals(b).드물게는지 확인해야 합 참조가 있습니다.에서 추상화 레벨을 다루는 논리적 표현의 물리적 객체 이것은 우리가 해야를 확인합니다.내가 생각하는 다른 의미한 ==Equals 실제로 혼동 될 수 있습니다..나는 그것을 믿어야 했 == 에 대한 가치 평등과 Equals 참조(또는 더 나은 이름처럼 IsSameAs)평등에서 첫 번째 장소입니다. 내가 사랑하는 것이 걸리지 않 MS 인 지침을 심각하게 여기지 않기 때문에 그렇지 않은 자연을 나뿐만 아니라,때문에 과부하 == 하지 않는 어떤 중요한 해입니다. 는 달리지 않을 재정의 비일반 EqualsGetHashCode 할 수 있는 물을 다시기 때문에,프레임 워크를 사용하지 않는 == 어디에서든지만 우리가 해결할 그것을 사용합니다.유일한 혜택을 얻 ==!= 것으로 일관성을 디자인의 전체 프레임 워크를 통해 내가 통제 할 수 없습니다.그리고 그 실제로 큰 것, 그래서 슬프게도 나는 그것에 스틱.

참조 의미론(변경 가능한 개체)

1)재정의 EqualsGetHashCode.

2)구현 IEquatable<T> 지 않을 해야 합니다,그러나 좋은 것 하나가있는 경우.

public class Entity : IEquatable<Entity>
{
    public bool Equals(Entity other)
    {
        if (ReferenceEquals(this, other))
            return true;

        if (ReferenceEquals(null, other))
            return false;

        //if your below implementation will involve objects of derived classes, then do a 
        //GetType == other.GetType comparison
        throw new NotImplementedException("Your equality check here...");
    }

    public override bool Equals(object obj)
    {
        return Equals(obj as Entity);
    }

    public override int GetHashCode()
    {
        throw new NotImplementedException("Your lightweight hashing algorithm, consistent with Equals method, here...");
    }
}

와 값을 의미론(불변의 객체)

이는 까다로운 부분입니다.쉽게 얻을 수 있습니다 엉망으로 처리하지 않으면..

1)재정의 EqualsGetHashCode.

2)오버로드 ==!=Equals. 을 위해 작동하는지 확인하 null.

2)구현 IEquatable<T> 지 않을 해야 합니다,그러나 좋은 것 하나가있는 경우.

public class Entity : IEquatable<Entity>
{
    public bool Equals(Entity other)
    {
        if (ReferenceEquals(this, other))
            return true;

        if (ReferenceEquals(null, other))
            return false;

        //if your below implementation will involve objects of derived classes, then do a 
        //GetType == other.GetType comparison
        throw new NotImplementedException("Your equality check here...");
    }

    public override bool Equals(object obj)
    {
        return Equals(obj as Entity);
    }

    public static bool operator ==(Entity e1, Entity e2)
    {
        if (ReferenceEquals(e1, null))
            return ReferenceEquals(e2, null);

        return e1.Equals(e2);
    }

    public static bool operator !=(Entity e1, Entity e2)
    {
        return !(e1 == e2);
    }

    public override int GetHashCode()
    {
        throw new NotImplementedException("Your lightweight hashing algorithm, consistent with Equals method, here...");
    }
}

각별한 관심을 기울이고 어떻게 해야 요금의 경우 클래스를 상속받을 수 있습,그러한 경우에 당신이 결정하는 경우 기본 클래스의 객체를 할 수 있습 같은 파생 클래스 개체입니다.이상적으로,없을 경우 객체의 파생된 클래스를 사용이 같은지 확인한 다음 기본 클래스의 인스턴스가 될 수 있다 동등한 파생 클래스의 인스턴스와 같은 경우에 없을 확인해야 Type 평등에 일반 Equals 의 기본 클래스입니다.

일반하지 않도록주 중복되는 코드.내가 만들 수 있는 일반적인 추상적인 기본 클래스(IEqualizable<T> 도)템플릿으로 허용한 다시 사용하기 쉽지만,슬프게도에서는 C#중지에서 나에서 파생되는 추가됩니다.

모든 답변을 위에 고려하지 않는 다형성,자주 당신이 원하는 파생에 대한 참조를 사용하여 파생 같을 때에도 비교를 통해 기본 참조.참조하시기 바랍 질문/토론/답- 평등과 다형성

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top