C# 是否有办法消除IComparable<;T>;运算符重载而不复制大量代码?

C# 是否有办法消除IComparable<;T>;运算符重载而不复制大量代码?,c#,operator-overloading,icomparable,C#,Operator Overloading,Icomparable,我有很多类型实现了IComparable。因为这些类型实现了该接口,所以提供以下重载是有意义的: /// <summary>Equality comparison operator.</summary> /// <param name="lhs">The left hand side.</param> /// <param name="rhs">The right hand side.</param> /// <ret

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

/// <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);
}
///相等比较运算符。
///左手边。
///右手边。
///如果等于,则为True;否则,错误。
公共静态布尔运算符==(T lhs,T rhs)
{
if(object.ReferenceEquals(lhs,null))
{
返回object.ReferenceEquals(rhs,null);
}
返回lhs.CompareTo(rhs)==0;
}
///不等式比较算子。
///左手边。
///右手边。
///如果不等于,则为True;否则,错误。
公共静态布尔运算符=(T左、T右)
{
返回!(lhs==rhs);
}
///小于比较运算符。
///左手边。
///右手边。
///如果小于,则为True;否则,错误。
公共静态布尔运算符(左、右)
{
返回rhs

这是大量需要反复重复的代码。是否有一些方法可以创建一个抽象类或其他东西(例如,C++的
std::rel_ops
),从而更容易实现这些功能?

有一种方法,但我不确定我是否会建议这样做。在这个例子中,为了简洁起见,我只定义了两个操作符。在其中一个例子中,我将
TemplateComparable
的实例强制转换为
T
,因为在类约束中,
T
确实必须继承自
TemplateComparable
,强制转换将有效

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;
    }
}
templatecompariable
实现
IComparable
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;
    }
}
抽象类TemplateCompariable:IComparable其中T:TemplateCompariable
{
公开摘要与其他文件进行比较;
公共静态布尔运算符==(模板可比lhs,T rhs)
{
if(ReferenceEquals(lhs,null))
{
返回ReferenceEquals(rhs,null);
}
返回右S.CompareTo(左S为T)==0;
}
公共静态布尔运算符!=(模板可比lhs、T rhs)
{
返回!(lhs==rhs);
}
}
Foo类:模板
{
公共覆盖整数比较(Foo其他)
{
//编写比较代码
返回0;
}
}

@BillyONeal它可以工作,但对我来说,它似乎有点像黑客。它的可读性不强,如果没有适当的文档,它可能无法维护。我会小心使用它。为什么
rhs
param a
T
而不是
templateCompariable
?@juharr为了简单起见。如果使用
TemplateComparable
则必须将其强制转换为
T
,因为
TemplateComparable
没有实现
IComparable
。您可以让它实现该接口并实现抽象成员,然后在派生类中重写它们,但我认为这会使示例变得太复杂。@Eve:比到处复制相同的50行代码更难维护?@BillyONeal这是我的观点,但是,虽然运算符重载为代码添加了语法糖,但上面的示例增加了类的复杂性,如果不能更改基类型,它甚至是不可用的。我得说,这真的取决于它在你的环境中有多有用。我理解在您的情况下,这有助于减少代码的冗余,我只是认为最好不要在没有适当文档的情况下使用。我看不出实现所有这些操作符有什么意义。IComparable只需要实现一个方法。如果必须将其分解(为什么?),则只需要==和<运算符来实现CompareTo()。在C++中思考这个问题很可能会妨碍你的工作。@汉斯:在C语言中,如果你执行了 ==,你必须执行<代码>!代码>,或编译错误结果。与
相同。如果您实现了
IComparable
,但没有实现所有这些运算符,FxCop会大喊大叫。您为什么要谈论实现运算符?IComparable根本不需要运算符。@Hans:是的,但FxCop需要:叹气。机器人每次都会打破常识。我想,仅仅实现IComparable来获得有序集合是不够的。
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;
    }
}