此声明为自动生成并插入,如文章中有特殊说明遵照说明。
转载前请务必事先联系并取得本人授权,同时需保留原文链接及明确的转载声明。未经许可,不得擅自用于商业用途。
Copyright © 2024-2025 SALTWOOD. All rights reserved.
转载前请务必事先联系并取得本人授权,同时需保留原文链接及明确的转载声明。未经许可,不得擅自用于商业用途。
Copyright © 2024-2025 SALTWOOD. All rights reserved.
最近 C# 13 更新了,在这里写一篇文章记录一下更新。
本次更新大致有以下内容:
1. 新的转义序列 \e
C# 13 引入了 \e
,用于表示 ESCAPE 字符(Unicode U+001B),使代码更直观。
string escapeSequence = "\e[31mRed Text\e[0m";
Console.WriteLine(escapeSequence);
2. 方法组自然类型改进
方法组类型推断更直观,减少了需要显式定义委托的场景。
Func<int, int> square = x => x * x;
// 不再需要显式类型声明
var squaredValues = new[] { 1, 2, 3 }.Select(x => square(x));
3. 从初始化器末尾开始的索引
索引运算符 ^ 可以用来倒序取值。
class Program
{
static void Main()
{
var x = new Numbers
{
Values =
{
[1] = 111,
[^1] = 999 // 从 C# 13 起能这么写
}
// x.Values[1] = 111
// x.Values[9] = 999,因为 [9] == [^1]
};
}
}
class Numbers
{
public int[] Values { get; set; } = new int[10];
}
4. 增强的 `params` 支持
params
现在支持任意类型的集合表达式,提升了灵活性。
void PrintItems(params List items)
{
foreach (var item in items) Console.WriteLine(item);
}
PrintItems(new List { "A", "B", "C" });
同时,现在也支持了多个 `params` 重载。如下:
public void WriteNames(params string[] names)
=> Console.WriteLine(String.Join(", ", names));
public void WriteNames(params ReadOnlySpan names)
=> Console.WriteLine(String.Join(", ", names));
public void WriteNames(params IEnumerable names)
=> Console.WriteLine(String.Join(", ", names));
// 调用 IEnumerable 那个
WriteNames(persons.Select(person => person.FirstName));
// 调用 string[] 那个
WriteNames(new string[] {"Mads", "Dustin", "Kathleen"});
// 调用 ReadOnlySpan 那个
WriteNames("Mads", "Dustin", "Kathleen");
5. `lock` 对象改进
新的 System.Threading.Lock
替代传统的 object
作为锁定对象。
public void MyMethod()
{
System.Threading.Lock myLock = new System.Threading.Lock();
lock (myLock)
{
// 此处
}
}
同时,如果 Lock
对象可能被当作 object
使用会出警告。
object lk = new Lock(); // 转换为不同类型的类型“System.Threading.Lock”的值将在“lock”语句中使用可能意外的基于监视器的锁定。
lock (lk)
{
// 做些什么
}
6. partial
属性
partial 现在可以应用于属性定义,特别适用于源生成器。
partial class Player
{
public partial int Level { get; set; } // 声明
}
partial class Player
{
public partial int Level // 实现
{
get => field;
set => field = Math.Max(0, Math.Min(100, value));
}
}
7. ref
和 unsafe
在异步方法和迭代器中的使用
放宽了 ref
和 unsafe
在异步方法中的限制。
unsafe Task UnsafeMethodAsync()
{
int value = 42;
int* ptr = &value;
return await Task.FromResult(*ptr);
}
8. 泛型类型参数的 allows ref struct
约束
支持在泛型类型中对 ref struct
类型的约束。
void Process(T value) where T : unmanaged
{
// 可以操作任意 unmanaged 类型
Console.WriteLine(value);
}
Process(42); // 可以传递 ref struct 类型
9. field
关键字
现在可以在属性内访问器背后的字段而不需要再手动创建一个。
class Player
{
public int Level
{
get => field; // field 指代属性背后的字段
set => field = Math.Max(0, Math.Min(100, value));
}
}
而在以前,需要这样写:
class Player
{
private int _level;
public int Level
{
get => this._level; // _level 相当于 field
set => this._level = Math.Max(0, Math.Min(100, value));
}
}