Я недавно наткнулся на интересную ошибку в коде сравнения, где два объекта имеют свойство равное 0.0m. Когда это свойство преобразуется в int и сравнивается, сравнение никогда не бывает равным. Воспроизводство ниже:C#: Почему следующее сравнение показывает, что 0! = 0
Возьмем абстракции А, и две реализации, В и С:
public abstract class A
{
public decimal MyProp { get; set; }
}
public class B : A
{
}
public class C : A
{
}
абстракции определяет несколько открытых свойств, в первую очередь, но не полностью, десятичной. Все общедоступные свойства всегда являются примитивными. Конкретные подтипы представляют эту абстракцию, полученную из двух разных источников данных. Два объекта типа A считаются равными тогда и только тогда, когда все их общедоступные свойства равны. Одна оговорка: все десятичные свойства должны быть преобразованы в int перед сравнением, используя поведение округления по умолчанию (MidpointRounding.ToEven). Это привело к следующему коду сравнения:
private static bool Compare(A a1, A a2)
{
var propertiesList = typeof(A).GetProperties(BindingFlags.Instance | BindingFlags.Public).ToList();
foreach (var propertyInfo in propertiesList)
{
var value1 = propertyInfo.GetValue(a1);
var value2 = propertyInfo.GetValue(a2);
if (propertyInfo.PropertyType == typeof(decimal))
{
value1 = Convert.ToInt32(value1);
value2 = Convert.ToInt32(value2);
}
// debugger confirms that value1 is 0 and value2 is 0
if (value1 != value2)
{
// yet these lines are always called
Console.WriteLine("The two A's are not equal");
return false;
}
}
return true;
}
Этот код предназначен для записи таким образом, чтобы:
A1.MyProp A2.MyProp Equal?
---------------------------------
0.0m 0.0m Yes
0.6m 1.4m Yes
1.5m 2.5m Yes
2.5m 3.5M No
Однако, как показано на следующее консольном приложении, первое использование корпуса (0.0m и 0.0m) всегда сбой:
private static void Main(string[] args)
{
var b = new B() { MyProp = 0.0m };
var c = new C() { MyProp = 0.0m };
// always false
var result = Compare(b, c);
}
Может ли кто-нибудь одолжить глаз и указать на ошибку в сравнительном коде?
Я подозреваю, что это связано с поведением Convert.ToInt32 (десятичное); Сейчас я занимаюсь расследованием. –