6

我想做这样的事情:

public override int CompareTo (Foo rhs)
{
    return Bar.CompareTo(rhs.Bar) ??
           Baz.CompareTo(rhs.Baz) ??
           Fuz.CompareTo(rhs.Fuz) ?? 0;
}

这不像书面的那样工作;有一些最小的解决方法可以让它工作吗?基本上我希望 0 链接到非零(或链结束)。

4

5 回答 5

2

基本上没有,但如果这样做会很好(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;
于 2011-10-24T20:09:22.667 回答
2

并非如此,??仅适用于空值(引用类型或可为空的结构)

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;
于 2011-10-24T20:09:26.077 回答
2

语言不支持。但是你可以像这样写一个小助手:

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);
}
于 2011-10-24T20:16:22.690 回答
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);
于 2016-08-24T20:39:05.387 回答
0

您还可以使用函数将零更改为 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;
}

对于带有 aGetNullIfEmptyGetNullIfWhiteSpace扩展名的惰性链接字符串操作,也有类似的方法。

于 2019-10-04T10:51:29.767 回答