链接以清理CompareTo

本文关键字:CompareTo 链接 | 更新日期: 2023-09-27 18:30:12

每次我需要在C#中编写CompareTo方法时,我都讨厌这样一个事实,即我不能像在JavaScript:中那样将测试和结果链接起来

function int compareTo(a, b) {
    return a.Value1 - b.Value1 || a.Value2 - b.Value2 || a.Value3 - b.Value3;
}

相反,在C#中,这看起来像:

int CompareTo(object obj)
{
    var other = obj as MyClass;
    if (other == null)
        return 0;
    int result = Value1 - other.Value1;
    if (result != 0)
        return result;
    result = Value2 - other.Value2;
    if (result != 0)
        return result;
    return Value3 - other.Value3;
}

有没有办法写出上面的"清洁剂"?它不必像JavaScript中那样是一行代码,但应该更可读,不易出错。

链接以清理CompareTo

使用通用扩展方法NullableCompareTo,我们现在可以使用?? operatorCompareTo方法重构为:

int CompareTo(object obj)
{
    var other = obj as MyClass;
    if (other == null)
        return 0;
    return Value1.NullableCompareTo(other.Value1)
        ?? Value2.NullableCompareTo(other.Value2)
        ?? Value3.CompareTo(other.Value3);
}

扩展方法

public static class ComparableExtensions
{
    /// <summary>
    /// Same as CompareTo but returns null instead of 0 if both items are equal.
    /// </summary>
    /// <typeparam name="T">IComparable type.</typeparam>
    /// <param name="this">This instance.</param>
    /// <param name="other">The other instance.</param>
    /// <returns>Lexical relation between this and the other instance or null if both are equal.</returns>
    public static int? NullableCompareTo<T>(this T @this, T other) where T : IComparable
    {
        var result = @this.CompareTo(other);
        return result != 0 ? result : (int?)null;
    }
}

您可以使用扩展方法来模拟??

public static class Extensions {
    public static T Coalesce<T>( this T self, T valueIfDefault ) {
        return self.Equals( default(T) ) ? valueIfDefault : self;
    }
}

例如,0.Coalesce(1).Coalesce(2)0.Coalesce(0).Coalesce(1)1.Coalesce(2).Coalesce(3)将分别为1。

你可以使用一个较短的名字,这取决于你个人对清晰与简洁的偏好。

以下是以这种风格改写的问题的比较方法:

int CompareTo(object obj) {
    var other = obj as MyClass;
    if( other == null )
        return 0;
    return (Value1 - other.Value1).Coalesce(Value2 - other.Value2)
                                  .Coalesce(Value3 - other.Value3);
}

如果个别比较比较比较昂贵,您还可以添加:

public static T Coalesce<T>( this T self, Func<T> valueIfDefault ) {
    return self.Equals( default(T) ) ? valueIfDefault() : self;
}

这将被称为类似(Value1 - other.Value1).Coalesce(() => CompareExpensively(Value2, other.Value2)).Coalesce(Value3 - other.Value3)