IEquatable接口检查为null时怎么办我在一个类中实现了IEquatable接口,代码如下。publicboolEquals(ClauseBEother){if(this._id==other._id){返回真;}返回假;}publicoverrideboolEquals(Objectobj){if(obj==null){returnbase.Equals(obj);}if(!(objisClauseBE)){thrownewInvalidCastException("'obj'参数不是ClauseBE对象。");}returnEquals(objasClauseBE);}publicoverrideintGetHashCode(){returnthis._id.GetHashCode();}publicstaticbooloperator==(ClauseBEa,ClauseBEb){//强制转换为对象,因此我们调用重载的Equals函数,该函数适当地检查b何时为null。返回a.Equals(b作为对象);}publicstaticbooloperator!=(ClauseBEa,ClauseBEb){//强制转换为对象,因此我们调用重载的Equals函数,它会适当地检查b何时为null。返回!a.Equals(b作为对象);这段代码在大多数情况下都有效。但是,下面的检查在equals运算符重载方法中抛出异常,因为a为null,所以没有Equals方法。if(this.Clause!=null){}解决这个问题的标准方法是什么?编辑我去过这个,但它看起来很麻烦。我希望有一种更优雅的方式来实现这一目标。publicstaticbooloperator==(ClauseBEa,ClauseBEb){if(aasobject==null&&basobject==null){返回真;}if((aasobject==null&&basobject!=null)||(basobject==null&&aasobject!=null)){returnfalse;}//转换为对象,因此我们调用重载的Equals函数,该函数适当地检查b何时为null。返回a.Equals(b作为对象);}publicstaticbooloperator!=(ClauseBEa,ClauseBEb){if(aasobject==null&&basobject==null){returnfalse;}if((aasobject==null&&basobject!=null)||(basobject==null&&aasobject!=null)){returntrue;}//转换为对象,因此我们调用重载的Equals函数,该函数适当地检查b何时为null.return!a.Equals(basobject);解决方案谢谢大家。我从每个人那里得到了很多很好的建议,我真的很感激。这是我最终得到的,它比我开始时更优雅。除了运算符重载之外,所有代码都是相同的。publicstaticbooloperator==(ClauseBEa,ClauseBEb){if(ReferenceEquals(a,null)&&ReferenceEquals(b,null)){返回真;}if(ReferenceEquals(a,null)||ReferenceEquals(b,null)){returnfalse;}返回a.Equals(b);}publicstaticbooloperator!=(ClauseBEa,ClauseBEb){return!(a==b);我总是发现用null处理运算符编写静态操作,并使Equals重写以“this”作为参数之一调用重载运算符。来自重载equals()和运算符==的指南(C#编程指南)//将此代码添加到先前定义的类ThreeDPoint//publicstaticbooloperator==(ThreeDPointa,ThreeDPointb){//如果两者均为空,或两者是同一个实例,返回真。如果(System.Object.ReferenceEquals(a,b)){返回真;}//如果一个为空,但不是两个都为空,则返回false。if(((object)a==null)||((object)b==null)){返回false;}//如果字段匹配则返回真:returnax==bx&&ay==by&&az==bz;}publicstaticbooloperator!=(ThreeDPointa,ThreeDPointb){return!(a==b);这就是ReSharper创建相等运算符并实现IEquatable的方式,我当然盲目地相信它;-)publicclassClauseBE:IEquatable{privateint_id;publicboolEquals(ClauseBEother){if(ReferenceEquals(null,other))returnfalse;如果(ReferenceEquals(this,other))返回true;返回other._id==this._id;}publicoverrideboolEquals(objectobj){if(ReferenceEquals(null,obj))returnfalse;如果(ReferenceEquals(this,obj))返回真;如果(obj.GetType()!=typeof(ClauseBE))返回false;返回等于((ClauseBE)obj);}publicoverrideintGetHashCode(){returnthis._id.GetHashCode();}publicstaticbooloperator==(ClauseBEleft,ClauseBEright){returnEquals(left,right);}publicstaticbooloperator!=(ClauseBEleft,ClauseBEright){return!Equals(left,right);}}检查null并返回false如果其中一个操作如果数字为null,则Equals应始终为false;我认为这比在检查null之前强制转换为Object要麻烦一点:ReferenceEquals(a,null)其他答案为一般问题提供了很好的解决方案。但是,您自己的代码可以简化为一个相对简单的解决方案...首先,在==运算符的开头,您有://首先测试if(aasobject==null&&basobject==null){返回真;这符合“工作太辛苦”的条件。如果ClauseBE是引用类型,那么你只需要与null进行比较——“作为对象”是多余的;同样,如果ClauseBE是值类型,则它永远不能为null。假设ClauseBE是引用类型(最有可能的情况),那么您可以对此进行简化-注意我们使用Object.Equals()来避免无限递归和堆栈井喷。//首先测试if(Object.Equals(a,null)&&Object.Equals(b,null)){returntrue;一个有用的快捷方式是使用Object.ReferenceEquals()-它会为您处理空值。所以你可以这样写://首先测试if(Object.ReferenceEquals(a,b)){returntrue;有了奖金,这也处理了a和b是完全相同的对象的情况。一旦通过了Object.ReferenceEquals()测试,您就会知道a和b是不同的。所以你的下一个测试://第二个测试if((aasobject==null&&basobject!=null)||(basobject==null&&aasobject!=null)){returnfalse;}可以简化-因为您知道如果a为null,则b不能为null,依此类推。//第二个测试if(Object.Equals(a,null)||Object.Equals(b,null)){returnfalse;如果此测试失败,则您知道a和b不同,并且两者都不是null。现在是调用重写的Equals()的好时机。//其余部分使用Equals()的实现returna.Equals(basobject);publicclassFoo:IEquatable{publicInt32Id{get;放;}publicoverrideInt32GetHashCode(){returnthis.Id.GetHashCode();}publicoverrideBooleanEquals(Objectobj){return!Object.ReferenceEquals(objasFoo,null)&&(this.Id==((Foo)obj).Id);//替代转换为Object以使用==运算符。return((Object)(objasFoo)!=null)&&(this.Id==((Foo)obj).Id);}publicstaticBooleanoperator==(Fooa,Foob){returnObject.Equals(a,b);}publicstaticBooleanoperator!=(Fooa,Foob){return!Object.Equals(a,b);}publicBooleanEquals(Fooother){returnObject.Equals(this,other);}}我使用了以下方法,它似乎对我有用。事情实际上,Resharper建议采用这种方法。publicboolEquals(FoopFoo){如果(pFoo==null)返回false;返回(pFoo.Id==Id);}publicoverrideboolEquals(objectobj){if(ReferenceEquals(obj,this))returntrue;返回等于(obj作为Foo);我更喜欢在Equals(T)方法中执行所有比较逻辑,并在重载到框架的运算符中保留“如果这个或那个为null,否则...”。覆盖运算符重载的唯一棘手之处在于,您不能再在Equals实现中使用这些运算符,例如与null进行比较。相反,object.ReferenceEquals可用于实现相同的效果。按照MSDN指南中OverDPidingEquals()和Operator==文章中的TwoDPoint示例,这是我在为类型实现值相等时生成的模式:publicoverrideboolEquals(objectobj){//注意:对于值类型,将使用://returnobjisTwoDPoint&&this.Equals((TwoDPoint)obj);返回this.Equals(obj作为TwoDPoint);}publicboolEquals(TwoDPointother){//注意:值类型不需要null检查。返回!object.ReferenceEquals(other,null)&&EqualityComparer.Default.Equals(this.X,other.X)&&EqualityComparer.Default.Equals(this.Y,other.Y);}publicstaticbooloperator==(TwoDPointleft,TwoDPointright){//System.Collections.Generic.EqualityComparer将对操作数执行null检查//并在必要时调用Equals重载。返回EqualityComparer.Default.Equals(左,右);}publicstaticbooloperator!=(TwoDPointleft,TwoDPointright){return!EqualityComparer.Default.Equals(left,right);上面的形式是最安全的实现,因为它只是将字段相等性检查转发给框架,不需要知道字段是否会重载相等运算符?如果您知道存在过载,可以简化它:publicboolEquals(TwoDPointother){return!object.ReferenceEquals(other,null)&&this.X==other。X&&this.Y==other.Y;您还可以在运算符重载时替换EqualityComparer调用,并在比较引用类型时调用静态object.Equals方法,或者当装箱值类型无关紧要时:publicstaticbooloperator==(TwoDPointleft,TwoDPointright){returnobject.Equals(左,右);}publicstaticbooloperator!=(TwoDPointleft,TwoDPointright){return!object.Equals(left,right);另请参见覆盖GetHashCode的最佳算法是什么?用于实现GetHashCode。以上就是C#学习教程:IEquatable接口检查null时怎么办。如果对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。涉及侵权,请点击维权联系管理员删除。如需转载请注明出处:
