.NET 10 新增功能概览
类库方面的改进
用字符串比较数字排序
在 .NET 10 中,System.String 类新增了 CompareAsNumbers 方法,用于按数字顺序比较字符串。这对于包含数字的字符串排序非常有用,例如文件名或版本号。
StringComparer numericStringComparer = StringComparer.Create(CultureInfo.CurrentCulture, CompareOptions.NumericOrdering);
Console.WriteLine(numericStringComparer.Equals("02", "2"));
// Output: True
foreach (string os in new[] { "Windows 8", "Windows 10", "Windows 11" }.Order(numericStringComparer))
{
Console.WriteLine(os);
}
// Output:
// Windows 8
// Windows 10
// Windows 11
HashSet<string> set = new HashSet<string>(numericStringComparer) { "007" };
Console.WriteLine(set.Contains("7"));
// Output: True
对十六进制字符串转换的 UTF-8 支持
.NET 10 在 Convert 类中增加了对十六进制字符串转换操作的 UTF-8 支持。 这些新方法提供了在 UTF-8 字节序列和十六进制表示形式之间转换的有效方法,而无需中间字符串分配:
Convert.FromHexString(ReadOnlySpan<Byte>)
Convert.FromHexString(ReadOnlySpan<Byte>, Span<Byte>, Int32, Int32)
Convert.TryToHexString(ReadOnlySpan<Byte>, Span<Byte>, Int32)
Convert.TryToHexStringLower(ReadOnlySpan<Byte>, Span<Byte>, Int32)
Convert.TryToHexStringUpper(ReadOnlySpan<Byte>, Span<Byte>, Int32)
禁止重复 JSON 属性的选项
JSON 规范不指定在反序列化 JSON 有效负载时如何处理重复属性。 这可能会导致意外的结果和安全漏洞。NET 10 引入了 JsonSerializerOptions.AllowDuplicateProperties 禁止重复 JSON 属性的选项。
var options = new JsonSerializerOptions
{
AllowDuplicateProperties = false
};
string json = @"{ ""Name"": ""Alice"", ""Name"": ""Bob"" }";
try
{
var person = JsonSerializer.Deserialize<Person>(json, options);
}
catch (JsonException ex)
{
Console.WriteLine($"JSON 反序列化失败: {ex.Message}");
}
SDK 中的改进
单次工具执行
现在 dotnet tool exec 可以使用命令执行 .NET 工具,而无需全局或本地安装该工具。
dotnet tool exec dotnetsay "Hello, World!"
新的 dnx 工具执行脚本
该 dnx 脚本提供了一种简化的方式来执行工具。
dnx dotnetsay "Hello, World!"
基于文件的应用程序
Console.WriteLine("Hello, World!");
可以通过将代码保存到名为 app.cs 的文件中并运行以下命令来执行:
dotnet run app.cs
#:package Colorful.Console@1.2.15
Colorful.Console.WriteAscii("Hello, World!");
可以通过将代码保存到名为 app.cs 的文件中并运行以下命令来执行:
dotnet run app.cs
更一致的命令顺序
.NET CLI 命令现在遵循更一致的顺序模式。下表显示了新的优先形式和别名:
| 新名词优先形式 | 别名 |
|---|---|
| dotnet package add | dotnet add package |
| dotnet package list | dotnet list package |
| dotnet package remove | dotnet remove package |
| dotnet reference add | dotnet add reference |
| dotnet reference list | dotnet list reference |
| dotnet reference remove | dotnet remove reference |
C# 14 中的新功能
扩展成员
扩展成员允许您为现有类型添加新方法、属性或事件,而无需修改原始类型的定义。 这对于向第三方库添加功能特别有用。
很久就支持的扩展方法
public static class StringExtensions
{
public static bool ContainsNumber(this string str)
{
return str.Any(char.IsDigit);
}
}
新增的扩展成员语法
public static class StringExtensions
{
// Extension block for string
extension(string source)
{
// Extension property:
public bool ContainsNumber => source.Any(char.IsDigit);
// Extension method:
public string Repeat(int count)
{
return string.Concat(Enumerable.Repeat(source, count));
}
}
// Static extension block for string
extension(string)
{
// Static extension method:
public static string Combine(string first, string second, string? separator = null)
{
return $"{first}{separator}{second}";
}
// Static extension property:
public static string SpaceChar => " ";
// Static user defined operator:
public static string operator * (string str, int count)
{
return string.Concat(Enumerable.Repeat(str, count));
}
}
}
使用示例:
string text = "Hello";
Console.WriteLine(text.ContainsNumber); // False
Console.WriteLine(text.Repeat(3)); // HelloHelloHello
string combined = string.Combine("Hello", "World", ", ");
Console.WriteLine(combined); // Hello, World
Console.WriteLine(string.SpaceChar); // " "
string repeated = "Hi" * 3;
Console.WriteLine(repeated); // HiHiHi
新增 field 关键字
private string _msg;
public string Message
{
get => _msg;
set => _msg = value ?? throw new ArgumentNullException(nameof(value));
}
可以简化为:
public string Message
{
get => field;
set => field = value ?? throw new ArgumentNullException(nameof(value));
}
未绑定泛型类型和 nameof
在 C# 14 中,nameof 运算符现在支持未绑定的泛型类型。这允许您获取泛型类型的名称,而无需指定类型参数。
Console.WriteLine(nameof(List<>)); // Output: List
Console.WriteLine(nameof(List<int>)); // Output: List
Console.WriteLine(nameof(Dictionary<,>)); // Output: Dictionary
自定义复合赋值
C# 14 允许您为自定义类型定义复合赋值运算符。这使得代码更简洁,并提高了可读性。
public class Point(int x, int y)
{
public int X { get; set; } = x;
public int Y { get; set; } = y;
public static Point operator +(Point a, Point b)
{
return new Point(a.X + b.X, a.Y + b.Y);
}
public static Point operator ++(Point p)
{
return new Point(p.X + 1, p.Y + 1);
}
}
使用示例:
Point p1 = new Point { X = 1, Y = 2 };
Point p2 = new Point { X = 3, Y = 4 };
Point p3 = p1 + p2; // Output: p3.X = 4, p3.Y = 6
p1++; // Now p1.X = 5, p1.Y = 7
Null 条件分配
在 C# 14 之前,在分配给属性之前,需要对变量进行 null 检查:
if (obj != null) // or obj is not null
{
obj.Property = newValue();
}
可以简化为:
obj?.Property = newValue();