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 aT
而不是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;
}
}