【问题标题】:IQueryable order by two or more propertiesIQueryable order by 两个或多个属性
【发布时间】:2023-03-14 01:49:01
【问题描述】:

我目前正在使用 IQueryable OrderBy 方法对自定义对象列表进行排序,如下所示:

mylist.AsQueryable().OrderBy("PropertyName");

现在我希望按多个属性进行排序。有没有办法做到这一点?

谢谢, 雅尼斯

【问题讨论】:

    标签: c# linq sorting c#-4.0 iqueryable


    【解决方案1】:
    OrderBy(i => i.PropertyName).ThenBy(i => i.AnotherProperty)
    

    在 OrderBy 和 ThenBy 中你必须提供 keySelector 函数,它从对象中选择 key 进行排序。因此,如果您只在运行时知道属性名称,那么您可以使用 Reflection 制作这样的函数,例如:

    var propertyInfo = i.GetType().GetProperty("PropertyName"); 
    var sortedList = myList.OrderBy(i => propertyInfo.GetValue(i, null)) 
    

    但是会比较慢,然后直接访问属性。您也可以使用 Linq.Expressions 即时“编译”此类函数,它的工作速度比反射快,但它不是很容易。或者您可以在 WPF 中使用 CollectionViewSource 及其排序功能。

    并且不要忘记 OrderBy() 返回排序后的可枚举并且它不会对您现有的列表进行就地排序。在您的示例中,您没有将排序列表保存到变量中。

    【讨论】:

    • 不过就是这样。 PropertyName 实际上是一个字符串(因为它来自排序选择器)。所以我不能用这个。有其他选择吗?
    • OrderBy 和 ThenBy 必须提供 keySelector 函数,从对象中选择键进行排序。使用字符串属性名称,您可以使用反射创建这样的函数:var propertyInfo = i.GetType().GetProperty("PropertyName"); myList.OrderBy(i => propertyInfo.GetValue(i, null)) 但它会更慢,然后直接访问属性。您也可以使用 Expressiosn 即时“编译”此类函数,它的工作速度比表达式快,但并不容易。或者您可以在 WPF 中使用 CollectionViewSource 及其排序功能
    • @Nikolay - 为什么不直接使用动态 Linq?
    • 是的,你也可以使用动态 linq 来获得你需要的东西。正如我在 Linq.Expressions 中提出的那样,动态 linq 本身会动态地从字符串创建表达式。了解内部的运作方式通常是件好事。但你是对的,在这种情况下最好只使用库
    【解决方案2】:

    你可以使用.ThenBy:

    var result = mylist
        .AsQueryable()
        .OrderBy(x => x.PropertyName)
        .ThenBy(x => x.SomeOtherProperty);
    

    【讨论】:

    • 不过就是这样。 PropertyName 实际上是一个字符串(因为它来自排序选择器)。所以我不能用这个。有其他选择吗?
    【解决方案3】:

    您可能希望使用 ThenBy 扩展方法能够按多个字段排序

     return myList.AsQueryable().OrderBy(m=>m.Property1).ThenBy(m => m.Property2);
    

    如果您想要动态 Linq,请查看 LinqKit。我最近从 here 实现了 Microsoft 的动态 Linq 库,并且能够使用字符串按两个字段排序。

    很棒的东西!不确定这是否会出现在 .NET 5 中。

    【讨论】:

    • 不过就是这样。 PropertyName 实际上是一个字符串(因为它来自排序选择器)。所以我不能用这个。有其他选择吗?
    【解决方案4】:

    正如其他人所建议的,您可以使用“ThenBy”。如果您想在使用之前将字符串转换为不同的值,这也是可能的,例如...

        var sortedSystemTestResultsList = systemTestResultsList.OrderBy(s =>
        {
            DateTime dt;
            if (!DateTime.TryParse(s.testPointCompletedDate, out dt)) return DateTime.MaxValue;
            return dt;
        }).ThenBy(s =>
        {
            Int32 tpID;
            if (!Int32.TryParse(s.testRunResultID, out tpID)) return Int32.MaxValue;
            return tpID;
        });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-15
      • 1970-01-01
      • 2020-10-11
      • 2016-11-22
      相关资源
      最近更新 更多