我刚写了一段代码,其行为与我预期的完全不同。 它似乎告诉我,我不知道关于物体的一切,所以我谦卑地转向堆叠溢出的同事的智慧,指出我正确的方向。
这是困扰我的代码:
[Test]
public void TestMySanity()
{
var oldSet = new Identifier[0];
var newSet = new[]
{
new Identifier("1"),
new Identifier("2")
};
var changes = uut.TrackChanges(oldSet, newSet, x => x).ToArray();
ChangeRecord<Identifier> xx = changes.FirstOrDefault(x => x.New != null && x.Old != null);
if (xx != null)
{
if (xx.Old != null && ((object) xx.Old) == null)
{
Console.WriteLine("How can something be not null and null at the same time?");
}
Assert.Fail("PS: this test expects a change record with Old = null and New = an Identifier");
}
}
要清楚 - &gt;此代码进入Console.WriteLine(...)
,这不应该发生......
我试图变得更聪明的一些事情:
Console.WriteLine("Is Object? " + (xx.Old is Object)); // = false
Console.WriteLine("Reference Equals? " + Object.ReferenceEquals(xx.Old, null)); // = true
try { Console.WriteLine(xx.Old.GetType().Name); }
catch (Exception ex)
{ Console.WriteLine("GetType() -> " + ex.Message);}
//Throws: Object reference not set to an instance of an object.
关于这个问题的评论似乎表明类标识符对于这个问题很重要,所以这里是:
public class Identifier : IComparable, IComparable<Identifier>, IEquatable<Identifier>
{
//Var
protected readonly IComparable Key;
//Constructor
public Identifier(IComparable key)
{
Key = key;
if (key == null) throw new ArgumentNullException("key");
}
//Hashcode (Must be overridden when equals is overridden.)
public override int GetHashCode()
{
return Key.GetHashCode();
}
public override string ToString()
{
return "[" + Key + "]";
}
//Compare
public virtual int CompareTo(object obj)
{
return CompareTo((Identifier)obj);
}
public virtual int CompareTo(Identifier other)
{
if (other == null) return 1;
return Key.CompareTo(other.Key);
}
//Equals
public override bool Equals(object obj)
{
return Equals((obj as Identifier));
}
public virtual bool Equals(Identifier other)
{
if (ReferenceEquals(null, other)) return false;
return Key.Equals(other.Key);
}
//Can be done because a Identifier is immutable
public static bool operator ==(Identifier A, Identifier B)
{
if (ReferenceEquals(A, null)) return false;
return A.Equals(B);
}
public static bool operator !=(Identifier A, Identifier B)
{
return !(A == B);
}
}
答案 0 :(得分:7)
发现错误:
public static bool operator ==(Identifier A, Identifier B)
{
if (ReferenceEquals(A, null)) return false;
return A.Equals(B);
}
如果B
为null
会怎样? A == B
应该返回true
,遗憾的是您的比较将return false
;
将其更改为:
if (ReferenceEquals(A, null)) return ReferenceEquals(B, null);
return A.Equals(B);
一般来说,通过强制转换为object
类似((object) xx.Old) == null
,您迫使C#编译器使用object==
运算符,它只执行object.ReferenceEquals(A, B)
,所以你绕过你的错误代码。
答案 1 :(得分:2)
==
和!=
运营商
public class MyX {
public MyY y {
get;
set;
}
}
public class MyY {
public static Boolean operator == (MyY left, Object right) {
return true;
}
public static Boolean operator != (MyY left, Object right) {
return true;
}
}
...
var x = new MyX();
if (x.y != null && (((Object) x.y) == null)) {
Console.Write("You've got it");
}
所以可能。