任何人都可以解释这种奇怪的行为,在C#中签花车? [英] Can anyone explain this strange behavior with signed floats in 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屋!