c# – 对于expr == null和expr!= null,与null的比较计算结果为true

c# – 对于expr == null和expr!= null,与null的比较计算结果为true,第1张

概述我看到一些非常奇怪的东西,我无法解释.我猜测我不熟悉的C#的一些边缘情况,还是运行时/发射器的错误? 我有以下方法: public static bool HistoryMessageExists(DBContext context, string id){ return null != context.GetObject<HistoryMessage>(id);} 在测试我的应用程序 我看到一些非常奇怪的东西,我无法解释.我猜测我不熟悉的C#的一些边缘情况,还是运行时/发射器的错误?

我有以下方法:

public static bool HistoryMessageExists(DBContext context,string ID){    return null != context.Getobject<HistoryMessage>(ID);}

在测试我的应用程序时,我看到它是不正常的 – 它为我知道的不存在于我的数据库的对象返回true.所以我停止了在方法和立即,我跑了以下:

context.Getobject<HistoryMessage>(ID)nullnull == context.Getobject<HistoryMessage>(ID)truenull != context.Getobject<HistoryMessage>(ID)true

Getobject的定义如下:

public T Getobject<T>(object pk) where T : DBObject,new(){    T rv = Connection.Get<T>(pk);    if (rv != null)    {        rv.AttachToContext(this);        rv.IsInserted = true;    }    return rv;}

有趣的是,当将表达式转换为对象时,正确评估比较:

null == (object)context.Getobject<HistoryMessage>(ID)truenull != (object)context.Getobject<HistoryMessage>(ID)false

没有平等的运算符覆盖.

编辑:事实证明有一个 *** 作符超载,这是不正确的.但是,为什么在内部方法通用Getobject中正确评估这个方法,在这种情况下,rv的类型为HistoryMessage.

public class HistoryMessage : EquatableIDentifiableObject{    public static bool HistoryMessageExists(DBContext context,string ID)    {        var rv = context.Getobject<HistoryMessage>(ID);        bool b = rv != null;        return b;    }    public static voID AddHistoryMessage(DBContext context,string ID)    {        context.InsertObject(new HistoryMessage { ID = ID });    }}public abstract partial class EquatableIDentifiableObject : DBObject,IObservableObject{    public event PropertyChangedEventHandler PropertyChanged;    [PrimaryKey]    public string ID { get; set; }    //...}public abstract partial class EquatableIDentifiableObject{    //...    public static bool operator ==(EquatableIDentifiableObject self,EquatableIDentifiableObject other)    {        if (ReferenceEquals(self,null))        {            return ReferenceEquals(other,null);        }        return self.Equals(other);    }    public static bool operator !=(EquatableIDentifiableObject self,null))        {            return !ReferenceEquals(other,null);        }        return !self.Equals(other);    }}public abstract class DBObject{    [Ignore]    protected DBContext Context { get; set; }    [Ignore]    internal bool IsInserted { get; set; }    //...}

这里发生了什么?

解决方法 >如你已经澄清的那样,== *** 作符失败,因为您的重载不正确.
>当转换为对象时,== *** 作符正常工作,因为它是被使用的对象的==的实现,而不是EquatableIDentifiableObject.
>在方法Getobject中, *** 作符正确地求值,因为它不是EquatableIDentifiableObject的正在使用的==的实现.在C#泛型中,运行时解析(至少在这里是相关的),而不是在编译时解决.注意==是静态而不是虚拟的.所以类型T在运行时被解析,但是调用==必须在编译时解决.在编译时,当编译器解析==它不会知道使用EquatableIDentifiableObject的==的实现.因为类型T有这个约束:其中T:DBObject,new(),DBObject的实现(如果有的话)将被使用.如果DBObject没有定义==,那么将使用第一个基类的实现(直到对象).

有关EquatableIDentifiableObject的实现的更多评论==:

>您可以替换此部分:

if (ReferenceEquals(self,null)){     return ReferenceEquals(other,null);}

有:

// If both are null,or both are the same instance,return true.if (object.ReferenceEquals(h1,h2)){    return true;}

>更换更有力

public static bool operator !=(EquatableIDentifiableObject self,EquatableIDentifiableObject other){    ...}

有:

public static bool operator !=(EquatableIDentifiableObject self,EquatableIDentifiableObject other){    return !(self == other);}

>为==定义签名的方法略有误导.第一个参数命名为self,第二个命名为other.如果==是一个实例方法就可以了.由于它是一种静态方法,所以名字自身有点误导.更好的名称将是o1和o2或沿着这条线的东西,以便两个 *** 作数在更平等的基础上对待.

总结

以上是内存溢出为你收集整理的c# – 对于expr == null和expr!= null,与null的比较计算结果为true全部内容,希望文章能够帮你解决c# – 对于expr == null和expr!= null,与null的比较计算结果为true所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1236862.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存