提问人:supercat 提问时间:11/19/2012 最后编辑:supercat 更新时间:11/20/2012 访问量:140
任何测试结构(尤其是包含“十进制”)的精确相等的好方法
Any nice way to test structures (esp containing `Decimal`) for exact equality
问:
在 4.0 之前的 .net 版本中,如果结构仅包含基元字段,则仅当所有字段都精确匹配时,结构的运算符才会返回。在 4.0 中,Microsoft 更改了此行为,以便具有类型字段的结构可以返回 true,如果相应的字段包含表示相同数值的值,即使它们在其他细节上不匹配(最值得注意的是,对于 ,仅在尾随零中不同的值被视为相等)。不幸的是,在某些情况下,这绝对是灾难性的。例如,给定两个不可变对象 和 ,如果 的所有字段都与 的字段完全匹配,则应该可以替换 。然而,为了保证这种换人的安全,比赛必须精确。如果 中的字段包含 0.1m,而 中的相应字段包含 0.10m,则不应将对象视为相等,因为 的可观察行为与 的可观察行为不同。Equals
true
Decimal
Decimal
X
Y
Y
X
X
Y
X
Y
Y
X
如果 Microsoft 没有覆盖这些类型以表示等价以外的其他含义(这是几乎所有其他类型的意思),则可以安全地假设,如果一个对象报告它是另一个对象,则后者的实例可以替代前者;即使给定了 上的非等价覆盖,也可以通过将这些类型包装在一个结构中来测试等价性。鉴于Microsoft不再允许这种等效性测试方法,必须做些什么才能获得相同的结果?是否有任何方法可以确定属性是定义自己的重写 [应该使用] 还是系统提供的重写 [在这种情况下,如果结构包含任何使用非等价的字段,它应该使用测试等价的相等运算符]?Equals
Equals
Decimal
AlternateEqualityComparer<T>.Default
Object.Equals
Equals
编辑我使用包含浮点类型以及 ;即使不是引用类型,它在结构中的存在也会导致自动生成的方法不对任何字段使用二进制比较。Decimal
Decimal
Equals
编辑 2下面是一个示例程序,显示了 .net 4.0 中的问题;我读到自早期版本的 .net 以来,该行为已发生变化,尽管该程序似乎在 2.0 和 4.0 上运行相同:
struct Test<T1,T2>
{
public T1 f1;
public T2 f2;
public Test(T1 p1, T2 p2)
{
f1 = p1;
f2 = p2;
}
}
class Program
{
static void DoCompares<T1,T2>(Test<T1,T2> thing1, Test<T1,T2> thing2)
{
Console.WriteLine("{0}/{1}/{2} {3}",
thing1.f1, thing2.f1, thing1.f1.Equals((Object)thing2.f1),
thing1.Equals(thing2));
}
static void DoTest<T1, T2>(T1 p1a, T1 p1b, T2 p2)
{
Test<T1,T2> thing1 = new Test<T1,T2>(p1a,p2);
Test<T1,T2> thing2 = new Test<T1,T2>(p1b,p2);
DoCompares(thing1, thing2);
}
static void Main(string[] args)
{
DoTest(1.0m, 1.00m, 1.0);
DoTest(1.0m, 1.00m, 1.0m);
DoTest(1.0 / (1.0 / 0.0), -1.0 / (1.0 / 0.0), 1.0m);
DoTest(1.0 / (1.0 / 0.0), -1.0 / (1.0 / 0.0), 1.0);
Console.ReadLine();
}
}
如果结构仅包含类型,则结构的相等比较器会报告结构不完全匹配。如果它包含一个类型的字段,即使它是一个不包含引用字段的结构,那么如果它们的数值相等,即使它们不等效,相等比较器也会将它们报告为相同。Double
Decimal
Decimal
无论如何,无论 .net 是否曾经坚持对对象进行二进制匹配,问题仍然存在:执行结构比较的最佳方法是什么,以便使用按位相等而不是数值相等来确定不包含引用类型字段的值类型的相等比较?有没有办法尊重结构类型的“显式”覆盖,同时为那些自动生成的结构类型使用替代相等比较器?Decimal
Equals
Equals
答: 暂无答案
评论
0.1m
0.10m
double
Decimal
Equals
double
float
Decimal