C# 객체는 null은 아니지만 (myObject! = null) 여전히 false를 반환합니다.

StackOverflow https://stackoverflow.com/questions/155458

  •  03-07-2019
  •  | 
  •  

문제

물체와 null을 비교해야합니다. 객체가 무효가되지 않으면 일부 데이터로 채 웁니다.

코드는 다음과 같습니다.

 if (region != null)
 {
  ....
 }

이것은 작동하지만 언젠가 반복 및 반복 할 때 영역 객체는 NULL이 아닙니다 (디버그 모드에서 내부 데이터를 볼 수 있음). 디버깅 할 때 단계별로 IF 문 안으로 들어 가지 않습니다 ... 다음 표현식으로 빠르게 감시 할 때 : (region == null) false를 반환하고 (region! = null을 봅니다. ) 거짓도를 반환 ... 왜 그리고 어떻게?

업데이트

누군가가 대상이 ==이고! = 과부하라고 지적합니다.

    public static bool operator ==(Region r1, Region r2)
    {
        if (object.ReferenceEquals(r1, null))
        {
            return false;
        }
        if (object.ReferenceEquals(r2, null))
        {
            return false;
        }

        return (r1.Cmr.CompareTo(r2.Cmr) == 0 && r1.Id == r2.Id);
    }


    public static bool operator !=(Region r1, Region r2)
    {
        if (object.ReferenceEquals(r1, null))
        {
            return false;
        }
        if (object.ReferenceEquals(r2, null))
        {
            return false;
        }
        return (r1.Cmr.CompareTo(r2.Cmr) != 0 || r1.Id != r2.Id);
    }
도움이 되었습니까?

해결책

== 및/또는! = 연산자가 지역 개체의 클래스에 대해 과부하되어 있습니까?

이제 과부하에 대한 코드를 게시 했으므로 다음과 같습니다.

오버로드는 아마도 다음과 같아야합니다 ( 존 스키트 그리고 필립 리크):

public static bool operator ==(Region r1, Region r2)
{
    if (object.ReferenceEquals( r1, r2)) {
        // handles if both are null as well as object identity
        return true;
    }

    if ((object)r1 == null || (object)r2 == null)
    {
       return false;
    }        

    return (r1.Cmr.CompareTo(r2.Cmr) == 0 && r1.Id == r2.Id);
}

public static bool operator !=(Region r1, Region r2)
{
    return !(r1 == r2);
}

다른 팁

해당 연산자 과부하가 고장났습니다.

첫째, == 호출하고 결과를 반전시킴으로써! =가 구현되면 인생이 훨씬 쉬워집니다.

둘째, 무효 점검 전에 ==가 있어야합니다.

if (object.ReferenceEquals(r1, r2))
{
    return true;
}

두 과부하가 모두 올바르지 않습니다

 public static bool operator ==(Region r1, Region r2)
    {
        if (object.ReferenceEquals(r1, null))
        {
            return false;
        }
        if (object.ReferenceEquals(r2, null))
        {
            return false;
        }

        return (r1.Cmr.CompareTo(r2.Cmr) == 0 && r1.Id == r2.Id);
    }

R1과 R2가 NULL 인 경우 첫 번째 테스트 (Object.Referenceequals (R1, NULL)) R2도 NULL이더라도 False를 반환합니다.

노력하다

//ifs expanded a bit for readability
 public static bool operator ==(Region r1, Region r2)
    {
        if( (object)r1 == null && (object)r2 == null)
        {
           return true;
        }
        if( (object)r1 == null || (object)r2 == null)
        {
           return false;
        }        
        //btw - a quick shortcut here is also object.ReferenceEquals(r1, r2)

        return (r1.Cmr.CompareTo(r2.Cmr) == 0 && r1.Id == r2.Id);
    }

동일한 데이터로 여러 스레드가 작동하는 경우 때때로 발생할 수 있습니다. 이 경우 자물쇠를 사용하여 서로를 엉망으로 만드는 것을 방지 할 수 있습니다.

"t"유형의 평등 비교를 위해이 방법을 과부하 시키십시오.

int GetHashCode() //Overrides Object.GetHashCode
bool Equals(object other) //Overrides Object.Equals; would correspond to IEquatable, if such an interface existed
bool Equals(T other) //Implements IEquatable<T>; do this for each T you want to compare to
static bool operator ==(T x, T y)
static bool operator !=(T x, T y)

유형 별 비교 코드는 한 곳에서 수행해야합니다.: 유형-안전 IEquatable<T> 인터페이스 방법 Equals(T other). 다른 유형 (T2)과 비교하는 경우 구현 IEquatable<T2> 또한 해당 유형의 필드 비교 코드를 Equals (T2)로 넣습니다.

모든 과부하 된 방법과 연산자는 평등 비교 작업을 기본 유형-안전 평등 (기타) 인스턴스 방법으로 전달하여 깨끗한 의존성 계층 구조가 유지되고 각 레벨에서 엄격한 보증이 도입되어 중복성과 비질의 복잡성을 제거합니다.

bool Equals(object other)
{
    if (other is T) //replicate this for each IEquatable<T2>, IEquatable<T3>, etc. you may implement
        return Equals( (T)other) ); //forward to IEquatable<T> implementation
    return false; //other is null or cannot be compared to this instance; therefore it is not equal
}

bool Equals(T other)
{
    if ((object)other == null) //cast to object for reference equality comparison, or use object.ReferenceEquals
        return false;
    //if ((object)other == this) //possible performance boost, ONLY if object instance is frequently compared to itself! otherwise it's just an extra useless check
        //return true;
    return field1.Equals( other.field1 ) &&
           field2.Equals( other.field2 ); //compare type fields to determine equality
}

public static bool operator ==( T x, T y )
{
    if ((object)x != null) //cast to object for reference equality comparison, or use object.ReferenceEquals
        return x.Equals( y ); //forward to type-safe Equals on non-null instance x
    if ((object)y != null)
        return false; //x was null, y is not null
    return true; //both null
}

public static bool operator !=( T x, T y )
{
    if ((object)x != null)
        return !x.Equals( y ); //forward to type-safe Equals on non-null instance x
    if ((object)y != null)
        return true; //x was null, y is not null
    return false; //both null
}

논의:

이전 구현은 유형 별 (즉, 필드 평등) 비교를 중앙 집중화합니다. IEquatable<T> 유형에 대한 구현. 그만큼 == 그리고 != 운영자는 평행하지만 반대 구현이 있습니다. 나는 이것을 다른 하나를 참조하는 것보다 이것을 선호하여 종속적 인 하나에 대한 추가 방법 호출이 있습니다. 만약 != 운영자는 단순히 전화를 걸 것입니다 == 연산자는 똑같이 수행하는 연산자를 제공하는 대신 사용하는 것만으로도 사용할 수도 있습니다. !(obj1 == obj2) 추가 방법 호출을 피하십시오. 비교-스펠은 평등 연산자와 IEquatable<T> 구현은 1. 불필요한 오버 헤드 및/또는 2를 소개 할 수 있기 때문에 구현.

내가 마음에 들지 않지만 언급 해야하는 대안은이 설정을 뒤집어 평등 연산자의 유형 별 평등 코드를 중앙 집중화하고 동등한 메소드가 이에 의존하는 것입니다. 그런 다음 바로 가기를 사용할 수 있습니다 ReferenceEquals(obj1,obj2) 필립이 이전 게시물에서 언급 한 것처럼 참조 평등과 널 평등을 동시에 확인하지만 그 아이디어는 오해의 소지가 있습니다. 하나의 돌로 두 마리의 새를 죽이는 것처럼 보이지만 실제로 더 많은 작품을 만들고 있습니다. 물체를 결정한 후에는 널이나 동일한 인스턴스가 아닙니다. 또한 각 인스턴스를 확인해야합니다. NULL입니다. 내 구현에서, 당신은 단일 인스턴스가 정확히 한 번 null인지 확인합니다. Equals 인스턴스 메소드가 호출 될 때, 이미 비교되는 첫 번째 객체가 NULL이라는 것을 이미 배제했습니다. 따라서 최대 두 번의 비교 후, 우리는 어떤 방법을 사용하든 현장 점검으로 직접 이동합니다 (Equals(object),Equals(T),==,!=). 또한, 내가 언급했듯이, 당신이 실제로 대부분의 시간을 비교하고 그 자체로 반대한다면, 현장 비교로 다이빙하기 직전에 평등 방법을 추가 할 수 있습니다. 마지막으로 추가하는 요점은 모든 레벨에서 중복/쓸모없는 점검을 도입하지 않고도 흐름/의존성 계층 구조를 유지할 수 있다는 것입니다.

여기서 이러한 수표가 옳지 않은 것입니다.

public static bool operator !=(Region r1, Region r2)
{
    if (object.ReferenceEquals(r1, null))
    {
        return false;
    }
    if (object.ReferenceEquals(r2, null))
    {
        return false;
    }
...

보고있는 매개 변수 옆에 새로 고침 아이콘을 클릭해야 할 가능성이 있습니다. vs는 모든 진술/매개 변수를 평가하지 않고 성능을 유지하려고 노력합니다. 관련이없는 장소를 변경하기 전에 확인하십시오.

bool comp;
if (object.IsNullOrEmpty(r1))
{
    comp = false;
}

if (object.IsNullOrEmpty(r2))
{
    comp = false;
}
return comp;
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top