C# (x.y!=null&;((对象)x.y)==null)怎么可能是真的?
我只是写了一段代码,它的行为与我预期的完全不同。 它似乎告诉我,我还不知道关于对象的一切,所以我谦虚地求助于stack overflow的同事们的智慧,为我指明了正确的方向 这就是让我困惑的代码:C# (x.y!=null&;((对象)x.y)==null)怎么可能是真的?,c#,C#,我只是写了一段代码,它的行为与我预期的完全不同。 它似乎告诉我,我还不知道关于对象的一切,所以我谦虚地求助于stack overflow的同事们的智慧,为我指明了正确的方向 这就是让我困惑的代码: [Test] public void TestMySanity() { var oldSet = new Identifier[0]; var newSet = new[] { new Identifier("1"), new Identifie
[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");
}
}
关于这个问题的评论似乎表明类标识符对于这个问题很重要,因此它是:
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);
}
}
公共类标识符:IComparable、IComparable、IEquatable
{
//变量
受保护的只读可比密钥;
//建造师
公共标识符(IComparable键)
{
钥匙=钥匙;
如果(key==null)抛出新的ArgumentNullException(“key”);
}
//Hashcode(重写equals时必须重写。)
公共覆盖int GetHashCode()
{
return Key.GetHashCode();
}
公共重写字符串ToString()
{
返回“[”+键+”];
}
//比较
公共虚拟整数比较(对象对象对象)
{
返回CompareTo((标识符)obj);
}
公共虚拟整数比较(标识符其他)
{
if(other==null)返回1;
返回Key.CompareTo(其他.Key);
}
//相等于
公共覆盖布尔等于(对象对象对象)
{
返回等于((obj作为标识符));
}
公共虚拟布尔等于(标识符其他)
{
if(ReferenceEquals(null,other))返回false;
返回Key.Equals(其他.Key);
}
//可以这样做,因为标识符是不可变的
公共静态布尔运算符==(标识符A、标识符B)
{
if(ReferenceEquals(A,null))返回false;
返回A等于(B);
}
公共静态布尔运算符!=(标识符A、标识符B)
{
返回!(A==B);
}
}
发现错误:
public static bool operator ==(Identifier A, Identifier B)
{
if (ReferenceEquals(A, null)) return false;
return A.Equals(B);
}
如果B
为null
,会发生什么情况A==B
应该返回true
,遗憾的是,您的比较将返回false
将其更改为:
if (ReferenceEquals(A, null)) return ReferenceEquals(B, null);
return A.Equals(B);
一般来说,要点是,通过像((object)xx.Old)=null
那样强制转换到对象
,你就迫使C编译器使用对象==
操作符,这只需要做一个对象。引用等于(a,B)
,所以你绕过了你的错误代码。用=
和的小把戏=代码>运算符,您就有了它
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;
}
}
所以这是可能的 我想这里有很多不相关的代码,你能阅读并应用吗?您还可以显示标识符
定义,或者在更改记录
中显示T
所使用的类型吗?它是一个结构类型还是(可为空)值类型,或者该类型是否有一个到对象的显式conversoin运算符?是否为标识符重新定义了运算符==
?是否为标识符定义了显式强制转换?我知道,如果不需要它来解决问题,我打算删除接口和类实现。请注意,interbase具有,其中T:class
,这使得它可以为空。在这种情况下,ChangeRecord将是ChangeRecord类型。我更新了问题以包含标识符类。啊,看来这确实是个问题。我要检查这些覆盖,看看我做错了什么。谢谢
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");
}