任何人都可以解释这种奇怪的行为,在C#中签花车? [英] Can anyone explain this strange behavior with signed floats in C#?

查看:147
本文介绍了任何人都可以解释这种奇怪的行为,在C#中签花车?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面是带有注释的例子:

Here is the example with comments:

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

那么,你怎么看这件事?

So, what do you think about this?

推荐答案

该错误是在以下两行 System.ValueType :(我走进参考源)

The bug is in the following two lines of System.ValueType: (I stepped into the reference source)

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

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

在所有的领域都是8字节宽, CanCompareBits 错误地返回true,从而导致两种不同的,但语义相同,值按位比较。

When the all of the fields are 8 bytes wide, CanCompareBits mistakenly returns true, resulting in a bitwise comparison of two different, but semantically identical, values.

在至少一个字段是不是8个字节宽, CanCompareBits 返回false,和code进入使用反射来遍历所有的领域,并调用等于的每个值,正确对待 -0.0 为等于 0.0

When at least one field is not 8 bytes wide, CanCompareBits returns false, and the code proceeds to use reflection to loop over the fields and call Equals for each value, which correctly treats -0.0 as equal to 0.0.

下面是源 CanCompareBits 从SSCLI:

Here is the source for CanCompareBits from SSCLI:

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#中签花车?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆