某种:
Documenti = Documenti
.OrderBy(o => string.IsNullOrEmpty(o.Note))
.ThenBy(o => Int32.TryParse(o.Note))
.ToList();
如果 o.Note 是 "" 或不是int
.
我该怎么做?
使用 C#7 或更高版本的每个人都滚动到底部,其他人都可以阅读原始答案:
是的,如果您将正确的参数传递给int.TryParse
. 两个重载都采用int
asout
参数并在内部使用解析值对其进行初始化。所以像这样:
int note;
Documenti = Documenti
.OrderBy(o => string.IsNullOrEmpty(o.Note))
.ThenBy(o => Int32.TryParse(o.Note, out note))
.ToList();
干净的方法是使用一种解析int
并在不可解析时返回的方法int?
:
public static int? TryGetInt(this string item)
{
int i;
bool success = int.TryParse(item, out i);
return success ? (int?)i : (int?)null;
}
现在您可以使用此查询(OrderByDescending
因为true
它“大于” false
):
Documenti = Documenti.OrderByDescending(d => d.Note.TryGetInt().HasValue).ToList();
它比使用 inint.TryParse
作为 out 参数的局部变量更干净。
Eric Lippert 评论了我的另一个答案,他举了一个例子,当它可能会受伤时:
C# LINQ:如何将 string("[1, 2, 3]") 解析为数组?
更新,这已经改变了 C#7。现在您可以在使用out
参数的地方直接声明变量:
Documenti = Documenti
.OrderBy(o => string.IsNullOrEmpty(o.Note))
.ThenBy(o => Int32.TryParse(o.Note, out int note))
.ToList();
Documenti = Documenti.OrderBy(o =>
int.TryParse(o.Note, out int val)
? val
: int.MaxValue /* or int.MinValue */
).ToList();
int.MaxValue
注意:在和之间切换int.MinValue
会将空值放在列表的前面或末尾。
编辑:2020-02-07 使用 C# 7 中引入的内联输出变量
您实际上可以在 lambda 表达式中放置更复杂的逻辑:
List<Doc> Documenti = new List<Doc>() {
new Doc(""),
new Doc("1"),
new Doc("-4"),
new Doc(null) };
Documenti = Documenti.OrderBy(o => string.IsNullOrEmpty(o.Note)).ThenBy(o =>
{
int result;
if (Int32.TryParse(o.Note, out result))
{
return result;
} else {
return Int32.MaxValue;
}
}).ToList();
foreach (var item in Documenti)
{
Console.WriteLine(item.Note ?? "null");
// Order returned: -4, 1, <empty string>, null
}
请记住,o => Int32.TryParse(...)
它只是创建仅o
作为参数接收并返回的委托的简写Int32.TryParse(...)
。只要它仍然是具有正确签名的语法正确方法,您就可以让它做任何您想做的事情(例如,所有代码路径都返回一个int
)
这不会产生预期的结果 b/cTryParse
返回 abool
而不是int
. 最简单的方法是创建一个返回int
.
private int parseNote(string note)
{
int num;
if (!Int32.TryParse(note, out num))
{
num = int.MaxValue; // or int.MinValue - however it should show up in sort
}
return num;
}
从您的排序中调用该函数
Documenti = Documenti
.OrderBy(o => parseNote(o.Note))
.ToList();
你也可以内联,但是,我认为一个单独的方法使代码更具可读性。我确信编译器会内联它,如果它是一种优化。
C# 7 有一些新特性使这变得更加容易
var ints = from a in str.Split(',').Select(s=> new { valid = int.TryParse(s, out int i), result = i })
where a.valid
select a.result;
或者当您专门询问排序时
var ints = from a in str.Split(',')
orderby (int.TryParse(s, out int i) ? i : 0 )
select a.result;