我可以在Linq Comparable中使用TryParse吗

本文关键字:TryParse Linq Comparable 我可以 | 更新日期: 2023-09-27 18:14:20

一种:

Documenti = Documenti
    .OrderBy(o => string.IsNullOrEmpty(o.Note))
    .ThenBy(o => Int32.TryParse(o.Note))
    .ToList();

如果o,这将"忽略"(不是顺序,放在末尾(。注意是"或不是int

我该怎么做?

我可以在Linq Comparable中使用TryParse吗

每个使用C#7或更新版本的人都可以滚动到底,其他人都可以阅读原始答案:


是的,如果您将正确的参数传递给int.TryParse,则可以。两个重载都将int作为out-参数,并在内部使用解析的值对其进行初始化。就像这样:

int note;
Documenti = Documenti
    .OrderBy(o => string.IsNullOrEmpty(o.Note))
    .ThenBy(o => Int32.TryParse(o.Note, out note)) 
    .ToList();

clean方法使用的方法解析为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,因为truefalse"大"(:

Documenti = Documenti.OrderByDescending(d => d.Note.TryGetInt().HasValue).ToList();

它比使用int.TryParse中使用的局部变量作为out参数更干净。

Eric Lippert评论了我的另一个答案,他举了一个可能会受伤的例子:

C#:字符串("[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.MaxValueint.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/c TryParse返回bool而不是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;