我想做这样的事情:
public override int CompareTo (Foo rhs)
{
return Bar.CompareTo(rhs.Bar) ??
Baz.CompareTo(rhs.Baz) ??
Fuz.CompareTo(rhs.Fuz) ?? 0;
}
这不像书面的那样工作;有一些最小的解决方法可以让它工作吗?基本上我希望 0 链接到非零(或链结束)。
基本上没有,但如果这样做会很好(IIRC,Jon 在深度 C# 中提到了类似的想法)。您可能可以链接条件,但我倾向于只使用:
int delta = Bar.CompareTo(rhs.Bar);
if(delta == 0) delta = Baz.CompareTo(rhs.Baz);
if(delta == 0) delta = Fuz.CompareTo(rhs.Fuz);
return delta;
并非如此,??
仅适用于空值(引用类型或可为空的结构)
int i;
i = Bar.CompareTo(rhs.Bar);
if (i != 0) return i;
i = Baz.CompareTo(rhs.Baz);
if (i != 0) return i;
i = Fuz.CompareTo(rhs.Fuz);
if (i != 0) return i;
return 0;
语言不支持。但是你可以像这样写一个小助手:
public override int CompareTo (Foo rhs)
{
return FirstNonZeroValue(
() => Bar.CompareTo(rhs.Bar),
() => Baz.CompareTo(rhs.Baz),
() => Fuz.CompareTo(rhs.Fuz));
}
private int FirstNonZeroValue(params Func<int>[] comparisons)
{
return comparisons.Select(x => x()).FirstOrDefault(x => x != 0);
}
如果不需要短路,你可以做一些二进制算术。 不要求比较结果必须是 -1、0 或 1,但它们必须是 < 0, = 0, > 0。因此,通过使用 2^n 作为系数,其中 n 是优先级,您可以总结 CompareTo 结果并根据需要得到一个 >0 或 <0 的数字。
所以,使用
return 4 * Bar.CompareTo(rhs.Bar)
+ 2 * Baz.CompareTo(rhs.Baz)
+ 1 * Fuz.CompareTo(rhs.Fuz);
您还可以使用函数将零更改为 null 并在没有以下情况下进行惰性评估Func<>
:
public override int CompareTo (Foo rhs) =>
Bar.CompareTo(rhs.Bar).GetNullIfZero() ??
Baz.CompareTo(rhs.Baz).GetNullIfZero() ??
Fuz.CompareTo(rhs.Fuz);
public static class IntExtensions
{
public static int? GetNullIfZero(this int i) => i == 0 ? null : (int?)i;
}
对于带有 aGetNullIfEmpty
和GetNullIfWhiteSpace
扩展名的惰性链接字符串操作,也有类似的方法。