簡體   English   中英

如何處理 IEqualityComparer 中的空值?

[英]How to handle nulls in IEqualityComparer?

以下方法來自 XUnit Assert class:

public static void Equal<T>(IEnumerable<T> expected, IEnumerable<T> actual, IEqualityComparer<T> comparer);

我將其用作:

IEnumerable<Decimal?> x = getXValues();
IEnumerable<Decimal?> y = getYValues();

Assert.Equal(x, y, new DecimalToleranceEqualityComparer(0.01m));

我正在使用IEqualityComparer ,因為可以考慮 2.526 等於 2.524。

我收到一個錯誤,因為DecimalToleranceEqualityComparer僅適用於Decimal ...

xy可能具有null值。 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();
    
    }

  } 

我想如果2個值是空值,它們應該被認為是相等的......

如何更改IEqualityComparer以使其處理空值?

這段代碼對我有用。 真正的訣竅在於Equals方法的實現。 還要記住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();
        }
    }
}

想到的一個選項可能是為可為空的十進制類型IEqualityComparer<decimal?>實現新的相等比較器,它可以在內部使用您現有的DecimalToleranceEqualityComparer 就像是

public Boolean Equals(Decimal? x, Decimal? y) {
    return (x.HasValue && y.HasValue)?
     _decimalToleranceEqualityComparer.Equals(x.Value,y.Value)
    : x == y;
} 

您正在提供一個Nullable<decimal>的列表,而您的IEqualityComparer需要一個Decimal的列表。

像這樣重寫你應該沒問題:

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