简体   繁体   English

C#对象不为null,但(myObject!= null)仍然返回false

[英]C# object is not null but (myObject != null) still return false

I need to do a comparaison between an object and NULL. 我需要在对象和NULL之间进行比较。 When the object is not NULL I fill it with some data. 当对象不是NULL时,我用一些数据填充它。

Here is the code : 这是代码:

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

This is working but when looping and looping sometime the region object is NOT null (I can see data inside it in debug mode). 这是有效的,但是当某个时候循环和循环时,region对象是非null(我可以在调试模式下看到其中的数据)。 In step-by-step when debugging, it doesn't go inside the IF statement... When I do a Quick Watch with these following expression : I see the (region == null) return false, AND (region != null) return false too... why and how? 在调试时一步一步,它不会进入IF语句...当我使用以下表达式进行快速监视时:我看到(region == null)返回false,AND(区域!= null )也返回错误... 为什么以及如何?

Update 更新

Someone point out that the object was == and != overloaded: 有人指出对象是==和!=重载:

    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);
    }

Is the == and/or != operator overloaded for the region object's class? 是否为区域对象的类重载了==和/或!=运算符?

Now that you've posted the code for the overloads: 现在您已经发布了重载代码:

The overloads should probably look like the following (code taken from postings made by Jon Skeet and Philip Rieck ): 重载应该如下所示(代码取自Jon SkeetPhilip Rieck的帖子):

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);
}

Those operator overloads are broken. 那些操作员过载被打破了。

Firstly, it makes life a lot easier if != is implemented by just calling == and inverting the result. 首先,如果通过调用==并反转结果来实现!=,它会使生活变得更加容易。

Secondly, before the nullity checks in == there should be: 其次,在无效检查之前==应该有:

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

Both of the overloads are incorrect 两个重载都不正确

 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);
    }

if r1 And r2 are null, the first test ( object.ReferenceEquals(r1, null) ) will return false, even though r2 is also null. 如果r1和r2为null,则第一个测试( object.ReferenceEquals(r1,null) )将返回false,即使r2也为null。

try 尝试

//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);
    }

This can sometimes happen when you have multiple threads working with the same data. 当多个线程使用相同的数据时,有时会发生这种情况。 If this is the case, you can use a lock to prevent them from messing with eachother. 如果是这种情况,您可以使用锁来防止它们互相混淆。

For equality comparison of a type "T", overload these methods: 对于类型“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)

Your type-specific comparison code should be done in one place : the type-safe IEquatable<T> interface method Equals(T other) . 特定于类型的比较代码应该在一个地方完成 :类型安全的IEquatable<T>接口方法Equals(T other) If you're comparing to another type (T2), implement IEquatable<T2> as well, and put the field comparison code for that type in Equals(T2 other). 如果要与另一种类型(T2)进行比较, IEquatable<T2>实现IEquatable<T2> ,并将该类型的字段比较代码放在Equals(T2 other)中。

All overloaded methods and operators should forward the equality comparison task to the main type-safe Equals(T other) instance method, such that an clean dependency hierarchy is maintained and stricter guarantees are introduced at each level to eliminate redundancy and unessential complexity. 所有重载的方法和运算符都应该将相等比较任务转发给主类型安全的Equals(T other)实例方法,以便维护干净的依赖关系层次结构,并在每个级别引入更严格的保证以消除冗余和不必要的复杂性。

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
}

Discussion: 讨论:

The preceding implementation centralizes the type-specific (ie field equality) comparison to the end of the IEquatable<T> implementation for the type. 前面的实现将特定于类型的(即字段相等)比较集中到该类型的IEquatable<T>实现的末尾。 The == and != operators have a parallel but opposite implementation. ==!=运算符具有并行但相反的实现。 I prefer this over having one reference the other, such that there is an extra method call for the dependent one. 我更倾向于将一个引用另一个引用,这样就可以为依赖引用一个额外的方法调用。 If the != operator is simply going to call the == operator, rather than offer an equally performing operator, then you may as well just use !(obj1 == obj2) and avoid the extra method call. 如果!=运算符只是调用==运算符,而不是提供一个性能相同的运算符,那么你也可以使用!(obj1 == obj2)并避免额外的方法调用。 The comparison-to-self is left out from the equals operator and the IEquatable<T> implementations, because it can introduce 1. unnecessary overhead in some cases, and/or 2. inconsistent performance depending on how often an instance is compared to itself vs other instances. 从equals运算符和IEquatable<T>实现省略了自我比较,因为它可能在某些情况下引入1.不必要的开销,和/或2.根据实例与自身的比较频率而不一致的性能与其他情况相比。

An alternative I don't like, but should mention, is to reverse this setup, centralizing the type-specific equality code in the equality operator instead and have the Equals methods depend on that. 我不喜欢,但应该提及的另一种方法是反转此设置,将类型特定的相等代码集中在相等运算符中,并使Equals方法依赖于此。 One could then use the shortcut of ReferenceEquals(obj1,obj2) to check for reference equality and null equality simultaneously as Philip mentioned in an earlier post, but that idea is misleading. 然后可以使用ReferenceEquals(obj1,obj2)的快捷方式来检查引用相等和空相等,正如Philip在之前的帖子中提到的那样,但这个想法具有误导性。 It seems like you're killing two birds with one stone, but your actually creating more work -- after determining the objects are neither both null nor the same instance, you will then, in addition, STILL have to on to check whether each instance is null. 看起来你是一石二鸟,但实际上你创造了更多的工作 - 在确定对象既不是空也不是同一个实例之后,你将会另外继续检查是否每个实例一片空白。 In my implementation, you check for any single instance being null exactly once. 在我的实现中,您检查任何单个实例只能为null一次。 By the time the Equals instance method is called, it's already ruled out that the first object being compared is null, so all that's left to do is check whether the other is null. 当调用Equals实例方法时,已经排除了被比较的第一个对象是null,所以剩下要做的就是检查另一个是否为null。 So after at most two comparisons, we jump directly into the field checking, no matter which method we use ( Equals(object),Equals(T),==,!= ). 因此,在最多两次比较之后,无论我们使用哪种方法( Equals(object),Equals(T),==,!= ),我们都会直接跳转到字段检查。 Also, as I mentioned, if you really are comparing and object to itself the majority of the time, then you could add that check in the Equals method just before diving into the field comparisons. 另外,正如我所提到的,如果你真的在大多数时间比较和反对自己,那么你可以在进入场比较之前在Equals方法中添加该检查。 The point in adding it last is that you can still maintain the flow/dependency hierarchy without introducing a redundant/useless check at every level. 最后添加它的要点是,您仍然可以维护流/依赖关系层次结构,而不会在每个级别引入冗余/无用检查。

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

if (object.IsNullOrEmpty(r2))
{
    comp = false;
}
return comp;

So is it that these checks here are not right: 那么这些检查是不正确的:

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

There's another possibility that you need to click the refresh icon next to the parameter that you're watching. 还有一种可能性是您需要单击您正在观看的参数旁边的刷新图标。 VS try to keep up with the performance while not evaluating every statement/parameter. VS尝试在不评估每个语句/参数的同时跟上性能。 Take a look to make sure, before you start making changes to places that's non relevant. 在开始更改不相关的地方之前,请先确认一下。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM