下面是带有注释的例子:

class Program
{
    // first version of structure
    public struct D1
    {
        public double d;
        public int f;
    }

    // during some changes in code then we got D2 from D1
    // Field f type became double while it was int before
    public struct D2 
    {
        public double d;
        public double f;
    }

    static void Main(string[] args)
    {
        // Scenario with the first version
        D1 a = new D1();
        D1 b = new D1();
        a.f = b.f = 1;
        a.d = 0.0;
        b.d = -0.0;
        bool r1 = a.Equals(b); // gives true, all is ok

        // The same scenario with the new one
        D2 c = new D2();
        D2 d = new D2();
        c.f = d.f = 1;
        c.d = 0.0;
        d.d = -0.0;
        bool r2 = c.Equals(d); // false! this is not the expected result        
    }
}

你觉得这个怎么样?


当前回答

我在http://blogs.msdn.com/xiangfan/archive/2008/09/01/magic-behind-valuetype-equals.aspx找到了答案。

核心部分是CanCompareBits上的源注释,它的ValueType。Equals用于确定是否使用memcmp样式的比较:

CanCompareBits的注释说 如果valuetype不是,则返回true 包含指针,是紧密的 包装”。和fastqualscheck使用 "memcmp"来加速比较。

作者继续阐述了OP所描述的问题:

假设你有一个结构 只包含一个浮点数。会发生什么 如果一个包含+0.0,另一个包含+0.0 包含-0.0 ?他们应该是 相同,但基本的二进制 表现方式不同。如果你 嵌套其他覆盖的结构 Equals方法,即优化 也会失败。

其他回答

简单的测试用例:

Console.WriteLine("Good: " + new Good().Equals(new Good { d = -.0 }));
Console.WriteLine("Bad: " + new Bad().Equals(new Bad { d = -.0 }));

public struct Good {
    public double d;
    public int f;
}

public struct Bad {
    public double d;
}

编辑:该错误也发生在float上,但仅在结构体中的字段加起来是8字节的倍数时才会发生。

我在http://blogs.msdn.com/xiangfan/archive/2008/09/01/magic-behind-valuetype-equals.aspx找到了答案。

核心部分是CanCompareBits上的源注释,它的ValueType。Equals用于确定是否使用memcmp样式的比较:

CanCompareBits的注释说 如果valuetype不是,则返回true 包含指针,是紧密的 包装”。和fastqualscheck使用 "memcmp"来加速比较。

作者继续阐述了OP所描述的问题:

假设你有一个结构 只包含一个浮点数。会发生什么 如果一个包含+0.0,另一个包含+0.0 包含-0.0 ?他们应该是 相同,但基本的二进制 表现方式不同。如果你 嵌套其他覆盖的结构 Equals方法,即优化 也会失败。

只是一个10年前的bug的更新:它已经在。net Core中被修复了(免责声明:我是这篇PR的作者),这可能会在。net Core 2.1.0中发布。

这篇博客文章解释了这个错误,以及我是如何修复它的。

这对我来说是真的,Mono的gmcs 2.4.2.3。

它必须是零相关的,因为改变了直线

D.d = -0.0

to:

D.d = 0.0

结果比较是正确的…