我看到了一些非常奇怪的东西,无法解释。我猜测这是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;
}
有趣的是,将表达式转换为
object
后,比较操作会被正确地执行: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, EquatableIdentifiableObject other)
{
if (ReferenceEquals(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; }
//...
}
这里发生了什么?
HistoryMessage
实现了相等运算符吗? - Lasse V. KarlsenHistoryMessage
的任何基类中也没有吗? - Lasse V. Karlsenceq
指令实现;如果存在运算符重载,则会看起来像call SomeClass.op_Equality
。您还可以在LINQPad中发现这一点,这是我尝试过的地方。 - Lasse V. KarlsenGetObject
中存在的 bug,导致连续调用返回不同的结果。将context.GetObject<HistoryMessage>(id)
缓存到本地变量中,然后检查是否为null
并查看问题是否仍然存在。 - InBetween