有没有一种简单的方法可以在C#中堆叠比较运算符?

Luc*_*key 6 c# comparison

在c#中,任何实现比较运算符的类型(例如< >)都可以轻松进行比较。例如,我可以这样做:

var date1 = new DateTime(1000);
var date2 = new DateTime(2000);
var date3 = new DateTime(3000);
var result = date1 < date2; // true
Run Code Online (Sandbox Code Playgroud)

但是,我无法执行以下操作

var result = date1 < date2 < date3; // error
Run Code Online (Sandbox Code Playgroud)

这不会编译,因为第一个比较返回的是布尔值,该布尔值无法与其他日期进一步比较

所以我必须像这样做(DateTime.CompareTo(DateTime)如果first DateTime早一点则返回-1 :

var result = date1.CompareTo(date2) + date2.CompareTo(date3) == -2; // true
Run Code Online (Sandbox Code Playgroud)

或简单地做到这一点:

var result = date1 < date2 && date2 < date3; // true
Run Code Online (Sandbox Code Playgroud)

但是,我想知道是否有可能<多次链接操作员,以便在更复杂的场景中使用时易于编写一些易于阅读的代码。

例如,我需要这样做(当然不会编译):

result = 
    date1 < date2 < date3 < date4 ||
    date3 < date4 < date1 < date2 ||
    date4 < date1 < date2 < date3 ||
    date2 < date3 < date4 < date1
Run Code Online (Sandbox Code Playgroud)

与上面介绍的可行方法相比,这将导致更容易阅读的代码。

有没有简单的方法可以执行此操作,我是否需要自己实施?

15e*_*153 4

这就是我要做的:

\n\n
public static class Extensions\n{\n    public static bool InOrderAscending<T>(this IEnumerable<T> values) \n        where T : struct, IComparable \n    =>\n        !values.Zip(values.Skip(1), (value, nextValue) => value.CompareTo(nextValue))\n             .Any(x => x >= 0);\n\n    public static bool InOrderAscending<T>(params T[] values) where T : struct, IComparable \n        => values.InOrderAscending();\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

其工作原理如下:Zip()采用两个 IEnumerables 并将它们中的项目枚举为匹配对:

\n\n
var a = new[] { 1, 2, 3 };\nvar b = new[] { 4, 5, 6, 7 };\n\nvar zipped = a.Zip(b, (aitem, bitem) => $"{aitem},{bitem}").ToList();\n
Run Code Online (Sandbox Code Playgroud)\n\n

压缩后将包含{ "1, 4", "2, 5", "3, 6" }.

\n\n

请注意,7未使用:没有匹配项,因此它被丢弃。这符合不必进行范围检查的 LINQ 理念。

\n\n

接下来,Skip(1)跳过一项并枚举其余项。

\n\n

所以我正在做的是压缩两个序列:原始序列,以及原始序列的第二个到最后一个项目。

\n\n
{a, b, c}\n{b, c}\n
Run Code Online (Sandbox Code Playgroud)\n\n

这样我们就得到了 (a, b) 和 (b, c) 的序列。

\n\n

这比与 相比可读性较差arg[i]arg[i+1]但它使您无需处理索引。

\n\n

所以我们的 zip 表达式返回一系列比较结果。对于每对相邻的项目,我们调用 CompareTo() 并返回结果。

\n\n
public static bool InOrderDescending<T>(params T[] values) where T : struct, IComparable\n{\n    List<int> comparisons = \n        values.Zip(values.Skip(1), (value, nextValue) => value.CompareTo(nextValue))\n              .ToList();\n\n    //  Now we finish by checking that sequence of integers for any positive values, \n    //  where a positive value means that `value` was greater than `nextValue`\n    var haveOutOfOrderItems = comparisons.Any(x => x >= 0);\n\n    //  If none of the values were positive, we\'re in order. \n    return !haveOutOfOrderItems;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

我仅为值类型编写了此方法,因此不必担心空值。大于null还是小于new Button()this.SettingsPage?这取决于调用者,所以我会编写一个引用类型重载,它接受类型的参数IComparer<T>,或者只是一个 lambda (编辑:也许我们实际上应该编写一个扩展方法来执行 self-offset-zip ,但从 lambda 返回某个任意返回类型的序列;我们\xe2\x80\x99d 使用它来编写这个)。

\n\n
public static bool InOrderAscending<T>(this IEnumerable<T> values, Func<T, T, int> compare) \n    where T : class \n=>\n    !values.Zip(values.Skip(1), (value, nextValue) => compare(value, nextValue))\n        .Any(x => x >= 0);\n
Run Code Online (Sandbox Code Playgroud)\n

  • 完美程度 - ed plunkett?;) (2认同)