18

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

这是代码:

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

这是可行的,但是当循环和循环时,区域对象不为空(我可以在调试模式下看到其中的数据)。在逐步调试时,它不会进入 IF 语句...当我使用以下表达式进行快速观察时:我看到 (region == null) 返回 false,AND (region != null ) 也返回 false ......为什么以及如何?

更新

有人指出该对象是 == 和 != 重载:

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

8 回答 8

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);
}
于 2008-09-30T22:51:49.570 回答
16

那些运算符重载被破坏了。

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

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

if (object.ReferenceEquals(r1, r2))
{
    return true;
}
于 2008-09-30T22:59:25.450 回答
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 为 null,则第一个测试 ( 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);
    }
于 2008-09-30T23:03:56.827 回答
3

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

于 2008-09-30T22:50:52.180 回答
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)并避免额外的方法调用。自我比较从等于运算符和IEquatable<T>实现中省略,因为它可能会引入 1. 在某些情况下不必要的开销,和/或 2. 不一致的性能取决于实例与自身与其他实例的比较频率。

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

于 2009-04-09T19:55:26.273 回答
0

那么这里的这些检查是不是不对:

public static bool operator !=(Region r1, Region r2)
{
    if (object.ReferenceEquals(r1, null))
    {
        return false;
    }
    if (object.ReferenceEquals(r2, null))
    {
        return false;
    }
...
于 2008-09-30T22:59:27.213 回答
0

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

于 2008-10-01T18:50:32.357 回答
0
bool comp;
if (object.IsNullOrEmpty(r1))
{
    comp = false;
}

if (object.IsNullOrEmpty(r2))
{
    comp = false;
}
return comp;
于 2012-11-22T20:04:55.183 回答