4.0 より前のバージョンの .net では、構造体にプリミティブ フィールドのみが含まれている場合、構造体のEquals
演算子は、true
すべてのフィールドが正確に一致した場合にのみ返されます。4.0 では、Microsoft はこの動作を変更しDecimal
、対応するフィールドが同じ数値量を表す値を保持している場合、タイプのフィールドを持つ構造体が true を返すことができるようにしましたDecimal
。ゼロは等しいと見なされました)。残念ながら、これが絶対に破滅的な状況がいくつかあります。たとえば、2 つの不変オブジェクトX
とが与えられた場合、 のすべてのフィールドが のフィールドと正確に一致する場合、Y
を代用できるはずですY
X
X
Y
. ただし、このような置換が安全であるためには、一致が正確であることが不可欠です。のフィールドに 0.1m が含まれX
、 の対応するフィールドにY
0.10m が含まれている場合、 の観察可能な動作が の動作と異なるため、オブジェクトは等しいと見なされません。Y
X
Equals
Microsoft がこれらの型を等価性以外の意味でオーバーライドしていなかった場合(これは、他のほぼすべての型が意味することです)、1 つのオブジェクトがEquals
別のオブジェクトを報告する場合、後者のインスタンスを代わりに使用できると安全に想定できます。前者; の非等価オーバーライドが与えられたとしても、Decimal
それらの型を構造体にラップすることで等価性をテストできます。マイクロソフトがその同等性テストの方法をもはや許可していないことを考えると、同じ結果を得るために何をしなければならないでしょうか? AlternateEqualityComparer<T>.Default
構造体が[使用する必要がある]独自のオーバーライドを定義するかObject.Equals
、システム提供のオーバーライドを定義するか[その場合、構造体に非等価ベースを使用するフィールドが含まれている場合]をプロパティが決定する方法はありますか?Equals
、等価性をテストする等価演算子を使用する必要があります]?
編集
浮動小数点型とDecimal
;を含む構造体を使用して動作をテストしました。は参照型ではありDecimal
ませんが、構造体内に存在するため、自動生成されたEquals
メソッドはどのフィールドに対してもバイナリ比較を使用しませんでした。
編集 2 .net 4.0 の問題を示すサンプル プログラムを次に示します。このプログラムは 2.0 と 4.0 で同じように動作するようですが、以前のバージョンの .net から動作が変更されたことを読んだことがあります。
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();
}
}
構造体に type のみが含まれている場合、構造Double
体の等値比較子は、構造体が完全に一致しない場合、構造体を別個のものとして報告します。Decimal
が参照フィールドを含まない構造体であっても、type のフィールドが含まれている場合Decimal
、等値比較子は、それらの数値が等しくなくても、それらの数値が等しい場合は同一であると報告します。
いずれにせよ、.net がオブジェクトのバイナリ マッチングを主張したことがあるかどうかにかかわらずDecimal
、疑問は残ります: 参照型フィールドを含まない値型の等価比較などの構造比較を実行する最良の方法は何でしょうか?は、数値の等価性ではなくビット単位の等価性を使用して決定されますか? 自動生成さEquals
れたものに代替等価比較器を使用している間に、構造型の「明示的な」オーバーライドを尊重する方法はありますか?Equals