[英]How to handle nulls in IEqualityComparer?
The following method is from XUnit Assert class:以下方法来自 XUnit Assert class:
public static void Equal<T>(IEnumerable<T> expected, IEnumerable<T> actual, IEqualityComparer<T> comparer);
And I am using it as:我将其用作:
IEnumerable<Decimal?> x = getXValues();
IEnumerable<Decimal?> y = getYValues();
Assert.Equal(x, y, new DecimalToleranceEqualityComparer(0.01m));
I am using an IEqualityComparer
because is fine to consider 2.526 equal to 2.524.我正在使用
IEqualityComparer
,因为可以考虑 2.526 等于 2.524。
I get an error because DecimalToleranceEqualityComparer
is only for Decimal
...我收到一个错误,因为
DecimalToleranceEqualityComparer
仅适用于Decimal
...
x
and y
might have null
values. x
和y
可能具有null
值。 DecimalToleranceEqualityComparer
is: DecimalToleranceEqualityComparer
是:
public class DecimalToleranceEqualityComparer : IEqualityComparer<Decimal> {
private readonly Decimal _tolerance;
public DecimalToleranceEqualityComparer(Decimal tolerance) {
_tolerance = tolerance;
}
public Boolean Equals(Decimal x, Decimal y) {
return Math.Abs(x - y) <= _tolerance;
}
public Int32 GetHashCode(Decimal obj) {
return obj.GetHashCode();
}
}
I suppose if 2 values are nulls they should be consider equal...我想如果2个值是空值,它们应该被认为是相等的......
How to change the IEqualityComparer
so that it handles nulls?如何更改
IEqualityComparer
以使其处理空值?
This code works for me.这段代码对我有用。 The real trick is in the imlementation of the
Equals
method.真正的诀窍在于
Equals
方法的实现。 Also keep in mind the null check in the GetHashCode
.还要记住
GetHashCode
中的 null 检查。
static void Main(string[] args)
{
IEnumerable<Decimal?> x = new List<Decimal?> { 1.51m, 3, null };
IEnumerable<Decimal?> y = new List<Decimal?> { 1.6m, 3, null };
Assert.Equal(x, y, new DecimalToleranceEqualityComparer(0.1m));
}
public class DecimalToleranceEqualityComparer : IEqualityComparer<Decimal?>
{
private readonly Decimal _tolerance;
public DecimalToleranceEqualityComparer(Decimal tolerance)
{
_tolerance = tolerance;
}
public Boolean Equals(Decimal? x, Decimal? y)
{
if (!x.HasValue && !y.HasValue)
{
// Both null -> they are equal
return true;
}
else if (!x.HasValue || !y.HasValue)
{
// One is null, other is not null -> not equal
return false;
}
else
{
// both have values -> run the actual comparison
return Math.Abs(x.Value - y.Value) <= _tolerance;
}
}
public Int32 GetHashCode(Decimal? obj)
{
if (obj.HasValue)
{
return obj.GetHashCode();
}
else
{
// Here decide what you need
return string.Empty.GetHashCode();
}
}
}
One option that comes to mind could be implementing new equality comparer for nullable decimal type IEqualityComparer<decimal?>
which could use your existing DecimalToleranceEqualityComparer
internally.想到的一个选项可能是为可为空的十进制类型
IEqualityComparer<decimal?>
实现新的相等比较器,它可以在内部使用您现有的DecimalToleranceEqualityComparer
。 Something like就像是
public Boolean Equals(Decimal? x, Decimal? y) {
return (x.HasValue && y.HasValue)?
_decimalToleranceEqualityComparer.Equals(x.Value,y.Value)
: x == y;
}
You are supplying a list of Nullable<decimal>
's and your IEqualityComparer
is expecting a list of Decimal
's.您正在提供一个
Nullable<decimal>
的列表,而您的IEqualityComparer
需要一个Decimal
的列表。
With a rewrite like this you should be fine:像这样重写你应该没问题:
public class DecimalToleranceEqualityComparer : IEqualityComparer<decimal?>
{
private readonly decimal _tolerance;
public DecimalToleranceEqualityComparer(decimal tolerance)
{
_tolerance = tolerance;
}
public bool Equals(decimal? x, decimal? y)
{
if (!x.HasValue && !y.HasValue) return true;
if (!x.HasValue || !y.HasValue) return false;
return Math.Abs(x.Value - y.Value) <= _tolerance;
}
public int GetHashCode(decimal? obj)
{
return obj.GetHashCode();
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.