【发布时间】:2016-06-01 08:02:04
【问题描述】:
我看到一些非常奇怪的东西,我无法解释。我猜是我不熟悉的 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是否实现了相等运算符? -
甚至不在
HistoryMessage的任何基类上? -
无论如何,你能告诉我们
HistoryMessage吗? -
此行为的另一个原因可能是赛车条件或
GetObject中的错误导致连续调用返回不同的结果。将context.GetObject<HistoryMessage>(id)缓存到局部变量,然后然后检查null是否相等,看看问题是否仍然存在。