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

我需要在对象和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); } 

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

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

重载应该如下所示(代码取自Jon Skeet和Philip Rieck的post):

 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) )将返回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); } 

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

对于类型“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; 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接口方法Equals(T other) 。 如果您要与另一个类型(T2)进行比较, IEquatable实现IEquatable ,并将该类型的字段比较代码放在Equals(T2 other)中。

所有重载的方法和运算符都应该将相等比较任务转发给主类型安全的Equals(T other)实例方法,以便维护干净的依赖关系层次结构,并在每个级别引入更严格的保证以消除冗余和不必要的复杂性。

 bool Equals(object other) { if (other is T) //replicate this for each IEquatable, IEquatable, etc. you may implement return Equals( (T)other) ); //forward to IEquatable 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实现的末尾。 ==!=运算符具有并行但相反的实现。 我更倾向于将一个引用另一个引用,这样就可以为依赖引用一个额外的方法调用。 如果!=运算符只是调用==运算符,而不是提供一个性能相同的运算符,那么你也可以使用!(obj1 == obj2)并避免额外的方法调用。 从equals运算符和IEquatable实现中省略了自我比较,因为它可能在某些情况下引入1.不必要的开销,和/或2.根据实例与自身的比较频率而不一致的性能与其他情况相比。

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

那么这些检查是不正确的:

 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;