== 연산자를 재정의합니다. null과 비교하는 방법? [복제]
아마도 이것에 대한 쉬운 대답이있을 것입니다 ...하지만 나를 피하는 것 같습니다. 다음은 간단한 예입니다.
public class Person
{
public string SocialSecurityNumber;
public string FirstName;
public string LastName;
}
이 특정 응용 프로그램에 대해 사회 보장 번호가 일치하고 두 이름이 일치하면 동일한 "사람"을 언급한다고 말하는 것이 타당합니다.
public override bool Equals(object Obj)
{
Person other = (Person)Obj;
return (this.SocialSecurityNumber == other.SocialSecurityNumber &&
this.FirstName == other.FirstName &&
this.LastName == other.LastName);
}
일관성을 유지하기 위해이 .Equals
방법을 사용하지 않는 팀의 개발자를 위해 == 및! = 연산자도 재정의합니다 .
public static bool operator !=(Person person1, Person person2)
{
return ! person1.Equals(person2);
}
public static bool operator ==(Person person1, Person person2)
{
return person1.Equals(person2);
}
괜찮아요?
그러나 Person 객체가 null
?
당신은 쓸 수 없습니다 :
if (person == null)
{
//fail!
}
이로 인해 == 연산자 재정의가 실행되고 코드가 다음에서 실패합니다.
person.Equals()
null 인스턴스에서는 메서드를 호출 할 수 없으므로 메서드 호출
반면에 무한 재귀 (및 스택 오버플로 [dot com])가 발생하기 때문에 == 재정의 내부에서이 조건을 명시 적으로 확인할 수 없습니다.
public static bool operator ==(Person person1, Person person2)
{
if (person1 == null)
{
//any code here never gets executed! We first die a slow painful death.
}
return person1.Equals(person2);
}
그렇다면 값 평등을 위해 == 및! = 연산자를 어떻게 재정의하고 여전히 null 개체를 설명합니까?
나는 대답이 고통스럽지 않기를 바랍니다. :-)
연산자 object.ReferenceEquals(person1, null)
대신 사용하십시오 ==
.
public static bool operator ==(Person person1, Person person2)
{
if (object.ReferenceEquals(person1, null))
{
return object.ReferenceEquals(person2, null);
}
return person1.Equals(person2);
}
나는 항상 이런 식으로 (== 및! = 연산자를 위해) 해왔으며 내가 만든 모든 객체에 대해이 코드를 재사용합니다.
public static bool operator ==(Person lhs, Person rhs)
{
// If left hand side is null...
if (System.Object.ReferenceEquals(lhs, null))
{
// ...and right hand side is null...
if (System.Object.ReferenceEquals(rhs, null))
{
//...both are null and are Equal.
return true;
}
// ...right hand side is not null, therefore not Equal.
return false;
}
// Return true if the fields match:
return lhs.Equals(rhs);
}
"! ="다음과 같이 진행됩니다.
public static bool operator !=(Person lhs, Person rhs)
{
return !(lhs == rhs);
}
편집 여기 에서 Microsoft의 제안 된 구현과 일치
하도록 ==
연산자 기능을 수정했습니다 .
당신은 항상 무시하고 넣어 수
(Object)(person1)==null
나는 이것이 확실하지 않을 것이라고 상상할 것이다.
The final (hypothetical) routine is below. It is very similar to @cdhowie's first accepted response.
public static bool operator ==(Person person1, Person person2)
{
if (Person.ReferenceEquals(person1, person2)) return true;
if (Person.ReferenceEquals(person1, null)) return false; //*
return person1.Equals(person2);
}
Thanks for the great responses!
//* - .Equals()
performs the null check on person2
Cast the Person
instance to object
:
public static bool operator ==(Person person1, Person person2)
{
if ((object)person1 == (object)person2) return true;
if ((object)person1 == null) return false;
if ((object)person2 == null) return false;
return person1.Equals(person2);
}
Overloading these operators consistently is pretty hard. My answer to a related question may serve as a template.
Basically, you first need to do a reference (object.ReferenceEquals
) test to see if the object is null
. Then you call Equals
.
Cast the Person to an Object and then perform the comparison:
object o1 = (object)person1;
object o2 = (object)person2;
if(o1==o2) //compare instances.
return true;
if (o1 == null || o2 == null) //compare to null.
return false;
//continue with Person logic.
cdhowie is on the money with the use of ReferenceEquals
, but it's worth noting that you can still get an exception if someone passes null
directly to Equals
. Also, if you are going to override Equals
it's almost always worth implementing IEquatable<T>
so I would instead have.
public class Person : IEquatable<Person>
{
/* more stuff elided */
public bool Equals(Person other)
{
return !ReferenceEquals(other, null) &&
SocialSecurityNumber == other.SocialSecurityNumber &&
FirstName == other.FirstName &&
LastName == other.LastName;
}
public override bool Equals(object obj)
{
return Equals(obj as Person);
}
public static bool operator !=(Person person1, Person person2)
{
return !(person1 == person2);
}
public static bool operator ==(Person person1, Person person2)
{
return ReferenceEquals(person1, person2)
|| (!ReferenceEquals(person1, null) && person1.Equals(person2));
}
}
And of course, you should never override Equals
and not override GetHashCode()
public override int GetHashCode()
{
//I'm going to assume that different
//people with the same SocialSecurityNumber are extremely rare,
//as optimise by hashing on that alone. If this isn't the case, change this
return SocialSecurityNumber.GetHashCode();
}
It's also worth noting that identity entails equality (that is, for any valid concept of "equality" something is always equal to itself). Since equality tests can be expensive and occur in loops, and since comparing something with itself tends to be quite common in real code (esp. if objects are passed around in several places), it can be worth adding as a shortcut:
public bool Equals(Person other)
{
return !ReferenceEquals(other, null) &&
ReferenceEquals(this, other) ||
(
SocialSecurityNumber == other.SocialSecurityNumber &&
FirstName == other.FirstName &&
LastName == other.LastName
);
}
Just how much of a benefit short-cutting on ReferenceEquals(this, other)
is can vary considerably depending on the nature of the class, but whether it is worth while doing or not is something one should always consider, so I include the technique here.
Easier than any of those approaches would be to just use
public static bool operator ==(Person person1, Person person2)
{
EqualityComparer<Person>.Default.Equals(person1, person2)
}
This has the same null equality semantics as the approaches that everyone else is proposing, but it's the framework's problem to figure out the details :)
참고URL : https://stackoverflow.com/questions/4219261/overriding-operator-how-to-compare-to-null
'Programing' 카테고리의 다른 글
롬복은 어떻게 작동합니까? (0) | 2020.07.02 |
---|---|
Pro JavaScript 프로그래머 인터뷰 질문 (답변 포함) (0) | 2020.07.02 |
조치 필터 속성에서 경로 재 지정 (0) | 2020.07.02 |
Android Studio 프로젝트를 빌드 할 때 Stacktrace 또는 디버그 옵션을 추가하는 방법 (0) | 2020.07.02 |
Swift 앱에서 로컬 데이터를 저장하는 방법은 무엇입니까? (0) | 2020.07.02 |