C# Linq 注意事项

Linq 中, GroupBy 之后 OrderBy

GroupBy().OrderBy() 是对 Key 进行的排序,所以想要对每组内的 Value 进行排序,需要 Foreach 之内对每个 Group 进行 OrderBy。

代码示例
using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication1
{
    internal class Program
    {
        static DateTime ParseDate(string date)
        {
            DateTime.TryParse(date, out var d);
            return d;
        }
        
        public static void Main(string[] args)
        {
            var students = new List<Student>
            {
                new Student { Info = new Info(){Name = "Alice", Score = 90, Date = ParseDate("9/14/2023  10:10:00 AM")}},
                new Student { Info = new Info(){Name = "Bob", Score = 85 , Date = ParseDate("9/14/2023  10:20:00 AM")}},
                new Student { Info = new Info(){Name = "Charlie", Score = 95 , Date = ParseDate("9/14/2023  10:12:00 AM")}},
                new Student { Info = new Info(){Name = "David", Score = 85 , Date = ParseDate("9/14/2023  10:13:00 AM")}},
                new Student { Info = new Info(){Name = "Kiz", Score = 85 , Date = ParseDate("9/14/2023  10:30:00 AM")}},
                new Student { Info = new Info(){Name = "Eve", Score = 92 , Date = ParseDate("9/14/2023  10:16:00 AM")}}
            };

            // 使用 GroupBy() 方法按分数分组
            var groupedStudents = students.GroupBy(student => student.Info.Score);

            // 对每个分组内的学生按分数降序排序,<b>这个结果只是在分组的排序,不是每个组内的排序</b>
            var sortedGroups = groupedStudents.OrderByDescending(group => group.Key);

            // 输出结果
            Console.WriteLine($"不对结果进行时间排序:");
            foreach (var group in sortedGroups.Where(t=>t.Key.Equals(85)))
            {
                Console.WriteLine($"分数: {group.Key}");
                foreach (var student in group)
                {
                    var info = student.Info;
                    Console.WriteLine($"  学生姓名: {info.Name}, {info.Score}, {info.Date}");
                }
            }
            // output:
            // 不对结果进行时间排序:
            // 分数: 85
            // 学生姓名: Bob, 85, 9/14/2023 10:20:00 AM  
            // 学生姓名: David, 85, 9/14/2023 10:13:00 AM
            // 学生姓名: Kiz, 85, 9/14/2023 10:30:00 AM  

            
            Console.WriteLine($"{Environment.NewLine}对结果进行时间排序:");
            foreach (var group in sortedGroups.Where(t=>t.Key.Equals(85)))
            {
                Console.WriteLine($"分数: {group.Key}");
                foreach (var student in group.OrderByDescending(t => t.Info.Date))
                {
                    var info = student.Info;
                    Console.WriteLine($"  学生姓名: {info.Name}, {info.Score}, {info.Date}");
                }
            }
            // output:
            // 对结果进行时间排序:
            // 分数: 85
            // 学生姓名: Kiz, 85, 9/14/2023 10:30:00 AM  
            // 学生姓名: Bob, 85, 9/14/2023 10:20:00 AM  
            // 学生姓名: David, 85, 9/14/2023 10:13:00 AM

        }
    }

    public class Student
    {
        public Info Info { get; set; }
    }

    public class Info
    {
        public string Name { get; set; }
        public int Score { get; set; }
        public DateTime Date { get; set; }
    }
}

FirstOrDefault 下的 Default

查看 Linq 中的 FirstOrDefault 方法中,发现最后找不到结果会返回一个 default(T),而 default 在给定不同的类型时又初始化为不同的值,有时为 null,有时又有值。

如果这时在 FirstOrDefault().Value 情况下使用,假设 T 是一些可为 null 的类型时,就会报可恶的 NullPointException,所以得额外注意,虽然可以使用 ?.Value 来避免,但是“代码编辑器”又会出现难看的波浪线提示。
官网介绍:https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/default

代码示例
using System;
using System.Collections.Generic;

Console.WriteLine(default(KeyValuePair<string, string>)); // output: [, ]
Console.WriteLine(default(System.Numerics.Complex));      // output: <0; 0>
Console.WriteLine(default(System.Collections.Generic.List<int>) is null); // output: True
Console.WriteLine(default(string) is null);     // output: True
Console.WriteLine(default(int));                // output: 0
Console.WriteLine(default(int?) is null);       // output: True
Console.WriteLine(default(object) is null);     // output: True
Console.WriteLine(default(object) is null);     // output: True
posted @ 2023-09-20 16:33  灵火  阅读(17)  评论(0编辑  收藏  举报