在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)
与上面介绍的可行方法相比,这将导致更容易阅读的代码。
有没有简单的方法可以执行此操作,我是否需要自己实施?
这就是我要做的:
\n\npublic 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}\nRun Code Online (Sandbox Code Playgroud)\n\n其工作原理如下:Zip()采用两个 IEnumerables 并将它们中的项目枚举为匹配对:
var a = new[] { 1, 2, 3 };\nvar b = new[] { 4, 5, 6, 7 };\n\nvar zipped = a.Zip(b, (aitem, bitem) => $"{aitem},{bitem}").ToList();\nRun Code Online (Sandbox Code Playgroud)\n\n压缩后将包含{ "1, 4", "2, 5", "3, 6" }.
请注意,7未使用:没有匹配项,因此它被丢弃。这符合不必进行范围检查的 LINQ 理念。
接下来,Skip(1)跳过一项并枚举其余项。
所以我正在做的是压缩两个序列:原始序列,以及原始序列的第二个到最后一个项目。
\n\n{a, b, c}\n{b, c}\nRun Code Online (Sandbox Code Playgroud)\n\n这样我们就得到了 (a, b) 和 (b, c) 的序列。
\n\n这比与 相比可读性较差arg[i],arg[i+1]但它使您无需处理索引。
所以我们的 zip 表达式返回一系列比较结果。对于每对相邻的项目,我们调用 CompareTo() 并返回结果。
\n\npublic 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}\nRun Code Online (Sandbox Code Playgroud)\n\n我仅为值类型编写了此方法,因此不必担心空值。大于null还是小于new Button()或this.SettingsPage?这取决于调用者,所以我会编写一个引用类型重载,它接受类型的参数IComparer<T>,或者只是一个 lambda (编辑:也许我们实际上应该编写一个扩展方法来执行 self-offset-zip ,但从 lambda 返回某个任意返回类型的序列;我们\xe2\x80\x99d 使用它来编写这个)。
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);\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
70 次 |
| 最近记录: |