c# – 对于expr == null和expr!= null,与null的比较计算结果为t
发布时间:2020-12-15 17:45:22 所属栏目:百科 来源:网络整理
导读:我看到一些非常奇怪的东西,我无法解释.我猜测我不熟悉的C#的一些边缘情况,还是运行时/发射器的错误? 我有以下方法: public static bool HistoryMessageExists(DBContext context,string id){ return null != context.GetObjectHistoryMessage(id);} 在测试
我看到一些非常奇怪的东西,我无法解释.我猜测我不熟悉的C#的一些边缘情况,还是运行时/发射器的错误?
我有以下方法: public static bool HistoryMessageExists(DBContext context,string id) { return null != context.GetObject<HistoryMessage>(id); } 在测试我的应用程序时,我看到它是不正常的 – 它为我知道的不存在于我的数据库的对象返回true.所以我停止了在方法和立即,我跑了以下: context.GetObject<HistoryMessage>(id) null null == context.GetObject<HistoryMessage>(id) true null != 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) true null != (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或沿着这条线的东西,以便两个操作数在更平等的基础上对待. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
推荐文章
站长推荐
热点阅读