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

时间:2008-09-30 22:49:03

标签: c# null compare

我需要在对象和NULL之间进行比较。当对象不是NULL时,我用一些数据填充它。

以下是代码:

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

这是有效的,但是当某个时候循环和循环时,region对象是非null(我可以在调试模式下看到其中的数据)。在调试时一步一步,它不会进入IF语句...当我使用以下表达式进行快速监视时:我看到(region == null)返回false,AND(区域!= 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);
    }

8 个答案:

答案 0 :(得分:29)

是否为区域对象的类重载了==和/或!=运算符?

现在您已经发布了重载代码:

重载应该如下所示(代码来自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);
}

答案 1 :(得分:16)

那些操作符重载已经破坏。

首先,如果通过调用==并反转结果来实现!=,它会让生活变得更轻松。

其次,在无效检查之前,= =应该有:

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

答案 2 :(得分:7)

两个重载都不正确

 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为空,则第一个测试( object.ReferenceEquals(r1,null))将返回false,即使r2也为null。

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

答案 3 :(得分:3)

当您有多个线程处理相同数据时,有时会发生这种情况。如果是这种情况,您可以使用锁定来防止它们互相弄乱。

答案 4 :(得分:2)

对于类型“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 other)中。

所有重载的方法和操作符都应该将相等比较任务转发给主类型安全的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
}

<强>讨论:

前面的实现将特定于类型的(即字段相等)比较集中到该类型的IEquatable<T>实现的末尾。 ==!=运算符具有并行但相反的实现。我更倾向于将一个引用另一个引用,这样就可以为依赖引用一个额外的方法调用。如果!=运算符只是调用==运算符,而不是提供同等效果的运算符,那么您也可以使用!(obj1 == obj2)并避免额外的方法调用。 从equals运算符和IEquatable<T>实现中省略了自我比较,因为它可能在某些情况下引入1.不必要的开销,和/或2.根据实例与之比较的频率而不一致的性能本身与其他实例相比。

我不喜欢,但应该提到的另一种方法是反转此设置,将类型特定的相等代码集中在相等运算符中,并使Equals方法依赖于此。然后,可以使用ReferenceEquals(obj1,obj2)的快捷方式同时检查引用相等和空均等,正如Philip在之前的帖子中提到的那样,但这个想法具有误导性。看起来你是一石二鸟,但实际上你创造了更多的工作 - 在确定对象既不是空也不是同一个实例之后,你将会另外继续检查是否每个实例一片空白。在我的实现中,您检查任何单个实例只能为null一次。当调用Equals实例方法时,已经排除了被比较的第一个对象是null,所以剩下要做的就是检查另一个是否为null。因此,在最多两次比较之后,无论我们使用哪种方法(Equals(object),Equals(T),==,!=),我们都会直接跳到字段检查中。另外,正如我所提到的,如果你真的在大多数时间比较和反对自己,那么你可以在进入场比较之前在Equals方法中添加该检查。最后添加它的重点是,您仍然可以维护流/依赖关系层次结构,而不会在每个级别引入冗余/无用检查。

答案 5 :(得分:0)

这里的检查是不正确的:

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

答案 6 :(得分:0)

还有一种可能性,您需要单击您正在观看的参数旁边的刷新图标。 VS尝试在不评估每个语句/参数的同时跟上性能。在开始更改不相关的地方之前,请先确认一下。

答案 7 :(得分:0)

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

if (object.IsNullOrEmpty(r2))
{
    comp = false;
}
return comp;
相关问题