简体   繁体   English

如何处理 IEqualityComparer 中的空值?

[英]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. xy可能具有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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM