Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# (x.y!=null&;((对象)x.y)==null)怎么可能是真的?_C# - Fatal编程技术网

C# (x.y!=null&;((对象)x.y)==null)怎么可能是真的?

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

我只是写了一段代码,它的行为与我预期的完全不同。 它似乎告诉我,我还不知道关于对象的一切,所以我谦虚地求助于stack overflow的同事们的智慧,为我指明了正确的方向

这就是让我困惑的代码:

[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");
}