这是带有注释的示例:

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
    }
}

所以,对于这个你有什么想法?

最佳答案

该错误在System.ValueType的以下两行中:(我进入了引用源)

if (CanCompareBits(this))
    return FastEqualsCheck(thisObj, obj);

(两种方法都是[MethodImpl(MethodImplOptions.InternalCall)])

当所有字段均为8个字节宽时,CanCompareBits错误地返回true,从而导致两个不同但在语义上相同的值的按位比较。

当至少一个字段的宽度不为8个字节时,CanCompareBits返回false,并且代码继续使用反射来遍历字段并为每个值调用Equals,从而正确地将-0.0视为0.0

这是来自SSCLI的CanCompareBits的来源:
FCIMPL1(FC_BOOL_RET, ValueTypeHelper::CanCompareBits, Object* obj)
{
    WRAPPER_CONTRACT;
    STATIC_CONTRACT_SO_TOLERANT;

    _ASSERTE(obj != NULL);
    MethodTable* mt = obj->GetMethodTable();
    FC_RETURN_BOOL(!mt->ContainsPointers() && !mt->IsNotTightlyPacked());
}
FCIMPLEND

关于c# - 谁能用C#中的带符号浮点数解释这种奇怪的行为?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2508945/

10-09 09:31