동등성이 제대로 작동하도록하려면 구조체에서 무엇을 재정의해야합니까?
제목에서 알 수 있듯이 ==
연산자 를 재정의해야 합니까? 방법은 .Equals()
어때? 내가 놓친 것이 있습니까?
msdn의 예
public struct Complex
{
double re, im;
public override bool Equals(Object obj)
{
return obj is Complex && this == (Complex)obj;
}
public override int GetHashCode()
{
return re.GetHashCode() ^ im.GetHashCode();
}
public static bool operator ==(Complex x, Complex y)
{
return x.re == y.re && x.im == y.im;
}
public static bool operator !=(Complex x, Complex y)
{
return !(x == y);
}
}
IEquatable <T>도 구현해야합니다. 다음은 프레임 워크 디자인 지침에서 발췌 한 것입니다.
값 유형에 IEquatable을 구현하십시오. 값 형식에 대한 Object.Equals 메서드는 boxing을 유발하며 기본 구현은 refection을 사용하기 때문에 그다지 효율적이지 않습니다. IEquatable.Equals는 훨씬 더 나은 성능을 제공 할 수 있으며 복싱을 유발하지 않도록 구현할 수 있습니다.
public struct Int32 : IEquatable<Int32> {
public bool Equals(Int32 other){ ... }
}
IEquatable.Equals를 구현할 때 Object.Equals를 재정의하는 것과 동일한 지침을 따르십시오. Object.Equals 재정의에 대한 자세한 지침은 섹션 8.7.1을 참조하십시오.
안타깝게도 다른 항목에 대해 논평 할만한 평판이 충분하지 않습니다. 그래서 여기에 최고의 솔루션에 대한 가능한 개선 사항을 게시하고 있습니다.
내가 틀렸다면 정정하지만 위에서 언급 한 구현
public struct Complex
{
double re, im;
public override bool Equals(Object obj)
{
return obj is Complex && this == (Complex)obj;
}
public override int GetHashCode()
{
return re.GetHashCode() ^ im.GetHashCode();
}
public static bool operator ==(Complex x, Complex y)
{
return x.re == y.re && x.im == y.im;
}
public static bool operator !=(Complex x, Complex y)
{
return !(x == y);
}
}
중대한 결함이 있습니다. 나는
public override int GetHashCode()
{
return re.GetHashCode() ^ im.GetHashCode();
}
XORing은 대칭이므로 Complex (2,1) 및 Complex (1,2)는 동일한 hashCode를 제공합니다.
우리는 아마도 다음과 같이 만들어야합니다.
public override int GetHashCode()
{
return re.GetHashCode() * 17 ^ im.GetHashCode();
}
대부분의 경우 구조체에서 Equals 및 GetHashcode를 구현하는 것을 피할 수 있습니다. 참조 멤버에 대해 비트 콘텐츠 + 리플렉션을 사용하는 Value 형식에 대한 컴파일러의 자동 구현이 있기 때문입니다.
해당 게시물을 살펴보십시오 : 데이터 저장소 Struct / Classes에 가장 적합한 것은 무엇입니까?
따라서 사용하기 쉽도록 == 및! =를 구현할 수 있습니다.
But most of the time you can avoid implementing Equals and GetHashcode.
A case where you'd have to implement Equals and GetHashCode is for a field that you don't wan't to take into account.
For instance a field that varies as time goes by like Age of a Person or instantSpeed of a car( the identity of the object shouldn't change if you want to find it back in the dictionary at the same place)
Regards, best code
The basic difference among the two is that the ==
operator is static, i.e. the appropriate method to invoke is determined at compile time, while the Equals
method is invoked dinamically on an instance.
Defining both is probably the best thing to do, even if this matters less in the case of structs, since structs cannot be extended (a struct can't inherit from another).
Just for completness I would also advice to overload Equals
method:
public bool Equals(Complex other)
{
return other.re == re && other.im == im;
}
this is a real spead improvement as there is no boxing occuring of the input argument of Equals(Object obj)
method
Some best practices for using value types:
- make them immutable
- override Equals (the one that takes an object as argument);
- overload Equals to take another instance of the same value type (e.g. * Equals(Complex other));
- overload operators == and !=;
- override GetHashCode
This comes from this post: http://theburningmonk.com/2015/07/beware-of-implicit-boxing-of-value-types/
'IT박스' 카테고리의 다른 글
IE11에서 Angular4 응용 프로그램 실행 문제 (0) | 2020.10.29 |
---|---|
html / css에서 이미지 옆에 세로 가운데 텍스트를 어떻게 입력합니까? (0) | 2020.10.29 |
Mac 가상 키 코드 목록은 어디에서 찾을 수 있습니까? (0) | 2020.10.29 |
javascript / jQuery에 isset of php와 같은 것이 있습니까? (0) | 2020.10.29 |
Django + Postgres : "현재 트랜잭션이 중단되고 트랜잭션 블록이 끝날 때까지 명령이 무시됩니다." (0) | 2020.10.29 |