我只是写了一段代码,它的行为与我预期的完全不同。
它似乎告诉我,我对对象还一无所知,所以我谦虚地求助于堆栈溢出同行的智慧,为我指明了正确的方向。

这是让我困惑的代码:

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

只是要清楚-> 此代码进入不应该发生的 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);
    }
}

最佳答案

发现错误:

public static bool operator ==(Identifier A, Identifier B)
{
    if (ReferenceEquals(A, null)) return false;
    return A.Equals(B);
}

如果 Bnull 会发生什么? 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) ,所以你绕过了你的错误代码。

关于c# - (x.y != null && ((object)x.y) == null) 怎么可能是真的?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36221113/

10-11 02:33
查看更多