隐藏的 NET 9 宝石
介绍
当微软宣布 .NET Framework 的新版本时,都会有发行说明。
发行说明并未涵盖所有新增功能。本文将通过 C# 示例介绍一些新功能。
可枚举.索引<T>
Enumerable.Index<T>返回一个将元素索引合并到元组中的可枚举值。
在使用 Index<T> 之前,有一种常规方法,即声明一个值为 -1 的 int 变量,并在 foreach 中增加该变量。
注意:
许多经验丰富的开发人员都使用这种方法,他们可能不太喜欢新的 Index 扩展方法,因为他们已经习惯了这种扩展方法。这种方法本身并没有问题。
示例 1
using static System.Globalization.DateTimeFormatInfo;
internal partial class Program
{
static void Main(string[] args)
{
var index = -1;
foreach (var month in Months)
{
++index;
Console.WriteLine($"{index,-5}{month}");
}
Console.ReadLine();
}
public static List<string> Months => CurrentInfo.MonthNames[..^1].ToList();
}
另一种方法是编写扩展方法。以下是网络上众多方法之一。
示例 2
using static System.Globalization.DateTimeFormatInfo;
internal partial class Program
{
static void Main(string[] args)
{
foreach (var (month, index) in Months.Index())
{
Console.WriteLine($"{index,-5}{month}");
}
Console.ReadLine();
}
public static List<string> Months => CurrentInfo.MonthNames[..^1].ToList();
}
public static class Extensions
{
public static IEnumerable<(T item, int index)> Index<T>(this IEnumerable<T> sender)
=> sender.Select((item, index) => (item, index));
}
上面的代码示例产生与上一个完全相同的输出。
示例 3
此示例是 NET9 原生的,不需要额外的扩展方法,在 .NET Core Framework 中使用Index 扩展。
internal partial class Program
{
static void Main(string[] args)
{
foreach (var (month, index) in Months.Index())
{
Console.WriteLine($"{index,-5}{month}");
}
Console.ReadLine();
}
public static List<string> Months => CurrentInfo.MonthNames[..^1].ToList();
}
上面的代码示例产生的输出与最后两个完全相同。
枚举.CountBy<TSource,TKey>
CountBy返回源序列中按键分组的元素数量。
CountBy 所需的代码比传统的 GroupBy 方法要少。
以下用于GroupBy和CountBy示例。
public class User
{
public int Id { get; set; }
public string UserName { get; set; }
public Role Role { get; set; }
}
public enum Role
{
Admin,
Member,
Guest
}
public static List<User> Users() =>
[
new() { Id = 1, UserName = "John", Role = Role.Admin },
new() { Id = 2, UserName = "Jane", Role = Role.Member },
new() { Id = 3, UserName = "Joe", Role = Role.Guest },
new() { Id = 4, UserName = "Alice", Role = Role.Admin },
new() { Id = 5, UserName = "Bob", Role = Role.Member },
new() { Id = 6, UserName = "Charlie", Role = Role.Guest },
new() { Id = 7, UserName = "Dave", Role = Role.Admin },
new() { Id = 8, UserName = "Eve", Role = Role.Member },
new() { Id = 9, UserName = "Frank", Role = Role.Guest },
new() { Id = 10, UserName = "Grace", Role = Role.Admin }
];
任务是获取每个角色的数量。
GroupBy 示例
private void GroupByWithCount()
{
var users = MockedData.Users();
var groupedUsers = users.GroupBy(user => user.Role)
.Select(group => new { Role = group.Key, Count = group.Count() });
foreach (var group in groupedUsers)
{
Debug.WriteLine($"Role: {group.Role}, Count: {group.Count}");
}
}
CountBy 示例
private void CountByWithCount()
{
var users = MockedData.Users();
foreach (var roleCount in users.CountBy(user => user.Role))
{
Debug.WriteLine($"There are {roleCount.Value} users with the role {roleCount.Key}");
}
}
这两个例子,除了输出结果略有不同外,都还算可以接受,但 CountBy 乍一看更容易让人理解它的功能。有些人会更喜欢其中一个,毕竟有选择总是好的。
聚合依据
AggregateBy对序列应用累加器函数,按键对结果进行分组。
以下用于GroupBy和AggregateBy示例。
public class User
{
public int Id { get; set; }
public string UserName { get; set; }
public Role Role { get; set; }
}
public enum Role
{
Admin,
Member,
Guest
}
public class MockedData
{
public static List<User> Users() =>
[
new() { Id = 1, UserName = "John", Role = Role.Admin },
new() { Id = 2, UserName = "Jane", Role = Role.Member },
new() { Id = 3, UserName = "Joe", Role = Role.Guest },
new() { Id = 4, UserName = "Alice", Role = Role.Admin },
new() { Id = 5, UserName = "Bob", Role = Role.Member },
new() { Id = 6, UserName = "Charlie", Role = Role.Guest },
new() { Id = 7, UserName = "Dave", Role = Role.Admin },
new() { Id = 8, UserName = "Eve", Role = Role.Member },
new() { Id = 9, UserName = "Frank", Role = Role.Guest },
new() { Id = 10, UserName = "Grace", Role = Role.Admin }
];
public static (string name, string department, int vacationDaysLeft)[] Employees =
[
("John Doe", "IT", 12),
("Eve Peterson", "Marketing", 18),
("John Smith", "IT", 28),
("Grace Johnson", "HR", 17),
("Nick Carson", "Marketing", 5),
("Grace Morgan", "HR", 9)
];
}
GroupBy 示例
private static void GroupByAggregateBySample()
{
var kvp = MockedData.Employees
.GroupBy(emp => emp.department)
.Select(group => new KeyValuePair<string, int>(group.Key, group.Sum(emp
=> emp.vacationDaysLeft)));
foreach (var (key, value) in kvp)
{
Debug.WriteLine($"Department {key,-15} has a total of {value} vacation days left.");
}
}
AggregateBy 示例
private static void AggregateBySample()
{
var kvp = MockedData.Employees
.AggregateBy(emp => emp.department, 0, (acc, emp)
=> acc + emp.vacationDaysLeft);
foreach (var (key, value) in kvp)
{
Debug.WriteLine($"Department {key,-15} has a total of {value} vacation days left.");
}
}
以上两者的输出相同。
Department IT has a total of 40 vacation days left.
Department Marketing has a total of 23 vacation days left.
Department HR has a total of 26 vacation days left.
UUID v7 生成
在 NET 9 之前,需要以下 NuGet 包UUIDNext来创建 UUID/GUID。
使用 NET 9。
//Creates a new Guid according to RFC 9562, following the Version 7 format.
var item1 = Guid.CreateVersion7();
//Creates a new Guid according to RFC 9562, following the Version 7 format with DateTimeOffset
var item2 = Guid.CreateVersion7(TimeProvider.System.GetUtcNow());
Debug.WriteLine(item1);
Debug.WriteLine(item2);
概括
NET 9 推出了几项新功能,这些功能在 Visual Studio 2022 的 17.12 版本中没有出现,可能会对开发人员有益。
源代码是在 Windows 窗体项目中完成的,这使得所有呈现的功能都可以在一个项目而不是多个项目中完成。
鏂囩珷鏉ユ簮锛�https://dev.to/karenpayneoregon/hidden-net-9-gems-3pb4