是否有一种方法可以在不重复大量代码的情况下消除IComparable <t>运算符重载?</t>

时间:2013-01-08 00:46:47

标签: c# operator-overloading icomparable

我有很多实现IComparable<T>的类型。因为这些类型实现了该接口,所以提供以下重载是有意义的:

/// <summary>Equality comparison operator.</summary>
/// <param name="lhs">The left hand side.</param>
/// <param name="rhs">The right hand side.</param>
/// <returns>True if <paramref name="lhs"/> is equal to <paramref name="rhs"/>; otherwise, false.</returns>
public static bool operator==(T lhs, T rhs)
{
    if (object.ReferenceEquals(lhs, null))
    {
        return object.ReferenceEquals(rhs, null);
    }

    return lhs.CompareTo(rhs) == 0;
}

/// <summary>Inequality comparison operator.</summary>
/// <param name="lhs">The left hand side.</param>
/// <param name="rhs">The right hand side.</param>
/// <returns>True if <paramref name="lhs"/> is not equal to <paramref name="rhs"/>; otherwise, false.</returns>
public static bool operator !=(T lhs, T rhs)
{
    return !(lhs == rhs);
}

/// <summary>Less than comparison operator.</summary>
/// <param name="lhs">The left hand side.</param>
/// <param name="rhs">The right hand side.</param>
/// <returns>True if <paramref name="lhs"/> is less than <paramref name="rhs"/>; otherwise, false.</returns>
public static bool operator <(T lhs, T rhs)
{
    if (lhs == null)
    {
        if (rhs == null)
        {
            return false;
        }
        else
        {
            return true;
        }
    }
    else
    {
        return lhs.CompareTo(rhs) < 0;
    }
}

/// <summary>Greater than comparison operator.</summary>
/// <param name="lhs">The left hand side.</param>
/// <param name="rhs">The right hand side.</param>
/// <returns>True if <paramref name="lhs"/> is greater than <paramref name="rhs"/>; otherwise, false.</returns>
public static bool operator >(T lhs, T rhs)
{
    return rhs < lhs;
}

/// <summary>Less than or equal comparison operator.</summary>
/// <param name="lhs">The left hand side.</param>
/// <param name="rhs">The right hand side.</param>
/// <returns>True if <paramref name="lhs"/> is less` than or equal to <paramref name="rhs"/>; otherwise, false.</returns>
public static bool operator <=(T lhs, T rhs)
{
    return !(rhs < lhs);
}

/// <summary>Greater than or equal comparison operator.</summary>
/// <param name="lhs">The left hand side.</param>
/// <param name="rhs">The right hand side.</param>
/// <returns>True if <paramref name="lhs"/> is greater than or equal to <paramref name="rhs"/>; otherwise, false.</returns>
public static bool operator >=(T lhs, T rhs)
{
    return !(lhs < rhs);
}

这是很多代码要反复重复。是否有一些创建抽象类或其他东西的方法(例如C ++的std::rel_ops)可以更容易地实现它们?

1 个答案:

答案 0 :(得分:1)

有一种方法,但我不确定我会建议它。在示例中,我仅为了简洁而定义了两个运算符。在其中一个中,我将TemplateComparable<T>的实例强制转换为T,因为在类约束中,T必须确实从TemplateComparable<T>继承,并且强制转换才有效。

abstract class TemplateComparable<T> where T : TemplateComparable<T>, IComparable<T>
{
    public static bool operator ==(TemplateComparable<T> lhs, T rhs)
    {
        if (ReferenceEquals(lhs, null))
        {
            return ReferenceEquals(rhs, null);
        }
        return rhs.CompareTo(lhs as T) == 0;
    }

    public static bool operator !=(TemplateComparable<T> lhs, T rhs)
    {
        return !(lhs == rhs);
    }
}

class Foo : TemplateComparable<Foo>, IComparable<Foo>
{
    public int CompareTo(Foo other)
    {
        //Write your comparison code
        return 0;
    }
}

样本用法:

var v1 = new Foo();
var v2 = new Foo();
var equals = v1 == v2; //equals will be true

TemplateComparable<T>实施IComparable<T>Foo的替代方案会覆盖其成员:

abstract class TemplateComparable<T> : IComparable<T> where T : TemplateComparable<T>
{
    public abstract int CompareTo(T other);

    public static bool operator ==(TemplateComparable<T> lhs, T rhs)
    {
        if (ReferenceEquals(lhs, null))
        {
            return ReferenceEquals(rhs, null);
        }
        return rhs.CompareTo(lhs as T) == 0;
    }

    public static bool operator !=(TemplateComparable<T> lhs, T rhs)
    {
        return !(lhs == rhs);
    }
}

class Foo : TemplateComparable<Foo>
{
    public override int CompareTo(Foo other)
    {
        //Write your comparation code
        return 0;
    }
}