C# OrderBy 扩展

public enum OrderByStatus
    {
        ASC,
        DESC
    }

    public static class OrderByHelper
    {
        public static IOrderedQueryable<T> OrderIf<T, TKey>(this IQueryable<T> source, Expression<Func<T, TKey>> order, OrderByStatus status, bool isEnable)
        {
            IOrderedQueryable<T> result = null;
            if (source != null && order != null)
            {
                if (isEnable)
                {
                    //已有OrderBy
                    if (source.ContainsOrderBy())
                    {
                        if (status == OrderByStatus.ASC)
                            result = (source as IOrderedQueryable<T>).ThenBy(order);
                        else
                            result = (source as IOrderedQueryable<T>).ThenByDescending(order);
                    }
                    else //未有 OrderBy
                    {
                        if (status == OrderByStatus.ASC)
                            result = source.OrderBy(order);
                        else
                            result = source.OrderByDescending(order);
                    }
                }
                else result = (source as IOrderedQueryable<T>);
            }
            return result;
        }

        /// <summary>
        /// 判断里面是否已经调用过 OrderBy、OrderByDescending 这两个函数否,
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool ContainsOrderBy<T>(this IQueryable<T> source)
        {
            bool result = false;


            var expression = source.Expression;

            if (expression.NodeType == ExpressionType.Call)
            {
                result = FindIOrderedQueryable(expression as MethodCallExpression);
            }

            return result;
        }

        /// <summary>
        /// 递归子项找到 OrderBy、OrderByDescending 这两个函数的调用,
        /// 其中一个子项有,就返回 True,都没有的话,就返回 False
        /// </summary>
        /// <param name="Expression"></param>
        /// <returns></returns>
        private static bool FindIOrderedQueryable(MethodCallExpression Expression)
        {
            bool result = false;

            if (Expression.Method.Name == "OrderBy" || Expression.Method.Name == "OrderByDescending")
            {
                result = true;
            }
            else
            {
                foreach (var item in Expression.Arguments)
                {
                    if (item.NodeType == ExpressionType.Call)
                    {
                        result = FindIOrderedQueryable(item as MethodCallExpression);
                        if (result) break;
                    }
                }
            }

            return result;
        }
    }


核心代码其实是 FindIOrderedQueryable 这个函数,靠这货找出表达式中是否有调用过 OrderBy 或者 OrderByDescending 函数。

然后扩展函数根据这个结果来判断,现在给 IQueryable 加上的函数是 OrderBy 还是 ThenBy,

以后再也不用为往 IQueryable 后边加上 OrderBy 还是 ThenBy 操心了,一直加 OrderIf 扩展函数就可以,扩展函数自动判断是加入哪个函数。

以下是调用的示例:

class Program
    {
        static void Main(string[] args)
        {
            List<MyModel> list = new List<MyModel>();

            for (int i = 0; i < 20; i++)
            {
                list.Add(new MyModel()
                {
                    CreatedAt = DateTime.Now,
                    ID = i + 1,
                    OrderNumber = i,
                    Name = Char.ConvertFromUtf32(i)
                });
            }

            var query = list.AsQueryable();
            query = query.Where(s => !string.IsNullOrEmpty(s.Name))
                .Where(s => !string.IsNullOrEmpty(s.Name))
                .Where(s => !string.IsNullOrEmpty(s.Name))
                .Where(s => !string.IsNullOrEmpty(s.Name))
                .Where(s => !string.IsNullOrEmpty(s.Name))
                .Where(s => !string.IsNullOrEmpty(s.Name))
                .Where(s => !string.IsNullOrEmpty(s.Name))
                .Where(s => !string.IsNullOrEmpty(s.Name))
                .Where(s => !string.IsNullOrEmpty(s.Name))
                .Where(s => !string.IsNullOrEmpty(s.Name))
                .Where(s => !string.IsNullOrEmpty(s.Name))
                .Where(s => !string.IsNullOrEmpty(s.Name))
                .Where(s => !string.IsNullOrEmpty(s.Name))
                .Where(s => !string.IsNullOrEmpty(s.Name))
                .Where(s => !string.IsNullOrEmpty(s.Name))
                .Where(s => !string.IsNullOrEmpty(s.Name))
                .Where(s => !string.IsNullOrEmpty(s.Name))
                .Where(s => !string.IsNullOrEmpty(s.Name))
                .Where(s => !string.IsNullOrEmpty(s.Name))
                .Where(s => !string.IsNullOrEmpty(s.Name))
                .Where(s => !string.IsNullOrEmpty(s.Name))
                .Where(s => !string.IsNullOrEmpty(s.Name))
                .Where(s => !string.IsNullOrEmpty(s.Name))
                .Where(s => !string.IsNullOrEmpty(s.Name))
                .Where(s => !string.IsNullOrEmpty(s.Name))
                .Where(s => !string.IsNullOrEmpty(s.Name));

            query = query
                .OrderIf(s => s.OrderNumber, OrderByStatus.DESC, true)
                .OrderIf(s => s.CreatedAt, OrderByStatus.ASC, true);

            query = query.Where(s => s.CreatedAt.HasValue);

            Console.WriteLine(query.ContainsOrderBy());
            Console.ReadLine();
        }
    }

    public class MyModel
    {
        [Key]
        public long ID { get; set; }
        public string Name { get; set; }
        public DateTime? CreatedAt { get; set; }
        public int? OrderNumber { get; set; }
    }


<think>嗯,用户之前问了关于C#中List的初始化赋值,现在又接着问LINQ的OrderBy怎么使用。看起来他们可能在处理数据集合,需要排序功能。用户可能是刚开始学习C#,或者需要复习相关知识。首先,我需要确认用户对LINQ的基础了解程度,但根据问题本身,可能他们已经接触过一些LINQ的基础操作,比如查询表达式或方法语法。 接下来,我要详细解释OrderBy的用法,包括基本升序、降序、多条件排序,还有可能涉及自定义排序的情况。可能需要分点说明,确保结构清晰。同时,应该比较查询表达式和方法语法两种写法,方便用户理解不同风格。 用户可能在实际应用中需要处理对象列表的排序,例如按照对象的某个属性排序,或者多个属性组合排序。这时候举一些实际的例子会很有帮助,比如用学生对象举例,按成绩、姓名等排序。此外,提到性能注意事项也很重要,尤其是当处理大数据量时,可能需要考虑效率问题。 还要注意用户可能不知道如何实现自定义比较器,或者如何结合其他LINQ方法使用OrderBy。这时候需要给出示例代码,比如使用ThenBy进行多级排序,或者用自定义的IComparer。此外,说明OrderBy和Order的区别,可能也是用户容易混淆的地方。 最后,检查是否有其他相关的内容需要补充,比如性能优化建议,或者常见的错误用法,帮助用户避免陷阱。确保回答全面,覆盖各种使用场景,并且语言简洁明了,适合不同层次的学习者理解。</think>在 C# 中,LINQ 的 `OrderBy` 是用于排序的核心操作符,以下是 6 种典型用法及详细说明: --- ### 一、基础排序(升序) ```csharp // 方法语法 var numbers = new List<int> { 5, 2, 8, 1 }; var ordered = numbers.OrderBy(n => n); // 结果:1,2,5,8 // 查询表达式语法 var query = from n in numbers orderby n select n; ``` --- ### 二、降序排序 ```csharp // 方法语法 var orderedDesc = numbers.OrderByDescending(n => n); // 结果:8,5,2,1 // 查询表达式语法 var query = from n in numbers orderby n descending select n; ``` --- ### 三、对象属性排序 ```csharp class Student { public string Name { get; set; } public int Score { get; set; } } var students = new List<Student> { new Student { Name = "Alice", Score = 85 }, new Student { Name = "Bob", Score = 90 } }; // 按分数降序排列 var sorted = students.OrderByDescending(s => s.Score); // Bob(90)在前 ``` --- ### 四、多条件排序 ```csharp // 方法语法(先按分数降序,同分按姓名升序) var multiSort = students .OrderByDescending(s => s.Score) .ThenBy(s => s.Name); // 查询表达式语法 var query = from s in students orderby s.Score descending, s.Name select s; ``` --- ### 五、自定义排序规则 ```csharp // 按字符串长度排序 var words = new List<string> { "apple", "kiwi", "banana" }; var customSort = words.OrderBy(w => w.Length); // kiwi(4),apple(5),banana(6) // 使用自定义比较器 class OddEvenComparer : IComparer<int> { public int Compare(int x, int y) => (x % 2).CompareTo(y % 2); } var nums = new List<int> { 3, 1, 4, 2 }; var oddEvenSort = nums.OrderBy(n => n, new OddEvenComparer()); // 偶数在后:3,1,4,2 ``` --- ### 六、动态排序(根据输入参数) ```csharp // 根据用户选择字段排序 string sortField = "Age"; var people = new List<Person>(); var dynamicSort = sortField switch { "Name" => people.OrderBy(p => p.Name), "Age" => people.OrderBy(p => p.Age), _ => people.OrderBy(p => p.Id) }; ``` --- ### 注意事项: 1. **延迟执行**:排序操作会延迟到实际枚举数据时执行 2. **性能**:对于大型数据集(10万+条目),建议先转换为数组再排序 ```csharp bigList.AsParallel().OrderBy(...) // 并行处理 ``` 3. **稳定性**:LINQ 排序是稳定的排序(相同键保持原始顺序) 4. **空值处理**:默认空值排在前面,可通过自定义比较器调整 ```csharp .OrderBy(x => x.Property, Comparer<Type>.Create((a,b) => a == null ? (b == null ? 0 : 1) : b == null ? -1 : a.CompareTo(b))) ``` --- ### 扩展技巧:`Order` vs `OrderBy` - C# 11+ 新增 `Order` 方法(随机排序): ```csharp var randomOrder = numbers.OrderBy(_ => Random.Shared.Next()); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值