무한 재귀없이 '=='연산자 과부하에서 null을 확인하려면 어떻게합니까?
다음은 == 연산자 오버로드 방법에서 무한 재귀를 발생시킵니다.
Foo foo1 = null;
Foo foo2 = new Foo();
Assert.IsFalse(foo1 == foo2);
public static bool operator ==(Foo foo1, Foo foo2) {
if (foo1 == null) return foo2 == null;
return foo1.Equals(foo2);
}
null을 어떻게 확인합니까?
사용 ReferenceEquals
:
Foo foo1 = null;
Foo foo2 = new Foo();
Assert.IsFalse(foo1 == foo2);
public static bool operator ==(Foo foo1, Foo foo2) {
if (object.ReferenceEquals(null, foo1))
return object.ReferenceEquals(null, foo2);
return foo1.Equals(foo2);
}
오버로드 메소드에서 오브젝트로 캐스트하십시오.
public static bool operator ==(Foo foo1, Foo foo2) {
if ((object) foo1 == null) return (object) foo2 == null;
return foo1.Equals(foo2);
}
사용하십시오 ReferenceEquals
. 로부터 MSDN 포럼 :
public static bool operator ==(Foo foo1, Foo foo2) {
if (ReferenceEquals(foo1, null)) return ReferenceEquals(foo2, null);
if (ReferenceEquals(foo2, null)) return false;
return foo1.field1 == foo2.field2;
}
시험 Object.ReferenceEquals(foo1, null)
어쨌든, ==
운영자 에게 과부하를주지 않는 것이 좋습니다 . 참조를 비교하고 Equals
"의미"비교를 위해 사용해야 합니다.
재정의 bool Equals(object obj)
하고 연산자를 원 ==
하고 Foo.Equals(object obj)
동일한 대답을 반환하려면 일반적으로 다음 !=
과 같이 연산자를 구현하십시오 .
public static bool operator ==(Foo foo1, Foo foo2) {
return object.Equals(foo1, foo2);
}
public static bool operator !=(Foo foo1, Foo foo2) {
return !object.Equals(foo1, foo2);
}
==
그런 다음 연산자 는 나를 위해 모든 null 검사를 수행 한 후 foo1.Equals(foo2)
두 개가 동일한 경우 실제 검사를 수행하도록 재정의했음을 호출 합니다.
C # 7 이상을 사용하는 경우 널 상수 패턴 일치를 사용할 수 있습니다.
public static bool operator==(Foo foo1, Foo foo2)
{
if (foo1 is null)
return foo2 is null;
return foo1.Equals(foo2);
}
이것은 하나의 호출 객체보다 약간 더 깔끔한 코드를 제공합니다 .ReferenceEquals (foo1, null)
내 접근 방식은
(object)item == null
내가 object
잘못 할 수없는 자체 평등 연산자 에 의존하고 있습니다. 또는 사용자 정의 확장 방법 (및 과부하) :
public static bool IsNull<T>(this T obj) where T : class
{
return (object)obj == null;
}
public static bool IsNull<T>(this T? obj) where T : struct
{
return !obj.HasValue;
}
또는 더 많은 경우를 처리하기 위해 다음이 될 수 있습니다.
public static bool IsNull<T>(this T obj) where T : class
{
return (object)obj == null || obj == DBNull.Value;
}
제한 조건 IsNull
은 값 유형을 방지 합니다. 지금은 전화만큼 달콤합니다
object obj = new object();
Guid? guid = null;
bool b = obj.IsNull(); // false
b = guid.IsNull(); // true
2.IsNull(); // error
which means I have one consistent/not-error-prone style of checking for nulls throughout. I also have found (object)item == null
is very very very slightly faster than Object.ReferenceEquals(item, null)
, but only if it matters (I'm currently working on something where I've to micro-optimize everything!).
To see a complete guide on implementing equality checks, see What is "Best Practice" For Comparing Two Instances of a Reference Type?
There is actually a simpler way of checking against null
in this case:
if (foo is null)
That's it!
This feature was introduced in C# 7
The static Equals(Object, Object)
method indicates whether two objects, objA
and objB
, are equal. It also enables you to test objects whose value is null
for equality. It compares objA
and objB
for equality as follows:
- It determines whether the two objects represent the same object reference. If they do, the method returns
true
. This test is equivalent to calling theReferenceEquals
method. In addition, if bothobjA
andobjB
arenull
, the method returnstrue
. - It determines whether either
objA
orobjB
isnull
. If so, it returnsfalse
. If the two objects do not represent the same object reference and neither isnull
, it callsobjA.Equals(objB)
and returns the result. This means that ifobjA
overrides theObject.Equals(Object)
method, this override is called.
.
public static bool operator ==(Foo objA, Foo objB) {
return Object.Equals(objA, objB);
}
replying more to overriding operator how to compare to null that redirects here as a duplicate.
In the cases where this is being done to support Value Objects, I find the new notation to handy, and like to ensure there is only one place where the comparison is made. Also leveraging Object.Equals(A, B) simplifies the null checks.
This will overload ==, !=, Equals, and GetHashCode
public static bool operator !=(ValueObject self, ValueObject other) => !Equals(self, other);
public static bool operator ==(ValueObject self, ValueObject other) => Equals(self, other);
public override bool Equals(object other) => Equals(other as ValueObject );
public bool Equals(ValueObject other) {
return !(other is null) &&
// Value comparisons
_value == other._value;
}
public override int GetHashCode() => _value.GetHashCode();
For more complicated objects add additional comparisons in Equals and a richer GetHashCode.
For a modern and condensed syntax:
public static bool operator ==(Foo x, Foo y)
{
return x is null ? y is null : x.Equals(y);
}
public static bool operator !=(Foo x, Foo y)
{
return x is null ? !(y is null) : !x.Equals(y);
}
A common error in overloads of operator == is to use
(a == b)
,(a ==null)
, or(b == null)
to check for reference equality. This instead results in a call to the overloaded operator ==, causing aninfinite loop
. UseReferenceEquals
or cast the type to Object, to avoid the loop.
check out this
// If both are null, or both are same instance, return true.
if (System.Object.ReferenceEquals(a, b))// using ReferenceEquals
{
return true;
}
// If one is null, but not both, return false.
if (((object)a == null) || ((object)b == null))// using casting the type to Object
{
return false;
}
reference Guidelines for Overloading Equals() and Operator ==
You can try to use an object property and catch the resulting NullReferenceException. If the property you try is inherited or overridden from Object, then this works for any class.
public static bool operator ==(Foo foo1, Foo foo2)
{
// check if the left parameter is null
bool LeftNull = false;
try { Type temp = a_left.GetType(); }
catch { LeftNull = true; }
// check if the right parameter is null
bool RightNull = false;
try { Type temp = a_right.GetType(); }
catch { RightNull = true; }
// null checking results
if (LeftNull && RightNull) return true;
else if (LeftNull || RightNull) return false;
else return foo1.field1 == foo2.field2;
}
'Programing' 카테고리의 다른 글
C # 3.0 개체 이니셜 라이저 생성자 괄호가 선택적인 이유는 무엇입니까? (0) | 2020.08.02 |
---|---|
왜 CURL이 반환되고 오류가 발생합니까? (23) 본문 작성에 실패 했습니까? (0) | 2020.08.02 |
Google Maps InfoWindow 스타일링 (0) | 2020.08.02 |
템플릿 바인딩과 바인딩은 무엇입니까? (0) | 2020.07.30 |
Rails 5 : 프로덕션 환경에서 lib 파일로드 (0) | 2020.07.30 |