Always keep a beginner's mind, don't forget the |

石起起

园龄:1年10个月粉丝:1关注:0

2025-02-05 17:55阅读: 53评论: 0推荐: 0

C# 版本 13 新增特性

C# 13 包括以下新功能。 可以使用最新的 Visual Studio 2022 版本或 .NET 9 SDK来尝试这些功能:

从 Visual Studio 17.12 开始,C# 13 将 field 上下文关键字作为预览功能包含在内。

C# 13 支持在 .NET 9上。 有关详细信息,请参阅 C# 语言版本控制

可以从 .NET 下载页下载最新的 .NET 9 SDK。 还可以下载 Visual Studio 2022,其中包括 .NET 9 SDK。

在公共预览版中提供新功能时,新功能将添加到“C# 中的新增功能”页。 roslyn 功能状态页工作集部分跟踪即将推出的功能何时合并到主分支中。

可以在我们关于重大更改的文章中找到 C# 13 中引入的任何重大更改。


参考文章:
C# 13(.Net 9) 中的新特性 - 扩展类型 - Rwing - 博客园
.NET 9 优化,抢先体验 C# 13 新特性 - 小码编匠 - 博客园
C# 13都新增了哪些高级功能?-duidaima 堆代码


params 集合

params 修饰符不限于数组类型。 现在可以将 params 用于任何已识别的集合类型,包括 System.Span<T>、System.ReadOnlySpan<T>,以及那些实现 System.Collections.Generic.IEnumerable<T> 并具有 Add 方法的类型。 除了具体类型外,还可以使用接口 System.Collections.Generic.IEnumerable<T>System.Collections.Generic.IReadOnlyCollection<T>System.Collections.Generic.IReadOnlyList<T>System.Collections.Generic.ICollection<T>和 System.Collections.Generic.IList<T>

使用接口类型时,编译器会合成所提供的参数的存储。 可以在 params 集合的功能规范中了解更多信息。

例如,方法声明可以将范围声明为 params 参数:

public void Concat<T>(params ReadOnlySpan<T> items)
{
    for (int i = 0; i < items.Length; i++)
    {
        Console.Write(items[i]);
        Console.Write(" ");
    }
    Console.WriteLine();
}

新的 lock 类型和语义

.NET 9 运行时包括线程同步的新类型,即 System.Threading.Lock 类型。 此类型通过其 API 提供更好的线程同步。 Lock.EnterScope() 方法进入独占范围。 从中返回的 ref struct 支持退出独占范围的 Dispose() 模式。

C# lock 语句可识别锁的目标是否为 Lock 对象。 如果是,则它使用更新的 API,而不是使用 System.Threading.Monitor的传统 API。 编译器还可以识别是否将 Lock 对象转换为另一种类型,并且将生成基于 Monitor 的代码。 可以在 新锁对象的功能规范中了解详细信息。

通过此功能,您可以通过更改对象 lock的类型来获得新库类型的优势。 无需更改其他代码。

新的转义序列 - \e

你可以使用 \e 作为 ESCAPE 字符 Unicode U+001B 的字符文本转义序列。 以前,你使用了 \u001b 或 \x1b。 不建议使用 \x1b,因为如果 1b 后面的下一个字符是有效的十六进制数字,则那些字符会成为转义序列的一部分。

方法组自然类型改进

此功能对涉及方法组的重载解析进行了小型优化。 _方法组_是一个方法,并且所有重载都具有相同的名称。 以前的行为是编译器为方法组构造完整的候选方法集。 如果需要自然类型,则自然类型是根据整套候选方法确定的。

新行为是在每个作用域内削减候选方法集,移除那些不适用的候选方法。 通常,被删除的方法是具有错误参数或不满足约束的泛型方法。 只有在没有找到候选方法的情况下,该过程才会继续到下一个外部作用域。 此过程更紧密地遵循重载解析的一般算法。 如果在给定范围内找到的所有候选方法不匹配,则方法组没有自然类型。

您可以在 提案规范中查看更改的详细信息。

对象初始值设定项中的隐式索引器访问

现在在对象初始化表达式中允许使用隐式“从末尾”索引运算符^。 例如,现在可以在对象初始值设定项中初始化数组,如以下代码所示:

public class TimerRemaining
{
    public int[] buffer { get; set; } = new int[10];
}

var countdown = new TimerRemaining()
{
    buffer =
    {
        [^1] = 0,
        [^2] = 1,
        [^3] = 2,
        [^4] = 3,
        [^5] = 4,
        [^6] = 5,
        [^7] = 6,
        [^8] = 7,
        [^9] = 8,
        [^10] = 9
    }
};

TimerRemaining 类包括初始化为长度为 10 的 buffer 数组。 前面的示例使用“from the end”索引运算符(^)将值赋给此数组,从而有效地创建从 9 到 0 的数组。

在 C# 13 之前的版本中,不能在对象初始值设定项中使用 ^ 运算符。 需要从前面为元素编制索引。

在迭代器和异步方法中启用 ref 局部变量和 unsafe 上下文

此功能和以下两项功能使 ref struct 类型能够使用新构造。 除非你编写自己的 ref struct 类型,否则你不会使用这些类型。 你更可能会看到间接的好处,因为 System.Span<T> 和 System.ReadOnlySpan<T>获得了更多的功能。

在 C# 13 之前,迭代器方法(使用 yield return的方法)和 async 方法无法声明局部 ref 变量,也不能具有 unsafe 上下文。

在 C# 13 中,async 方法可以声明 ref 局部变量或 ref struct 类型的局部变量。 但是,无法跨 await 边界访问这些变量。 也不能跨越 yield return 边界访问它们。

这种宽松的限制使编译器能够在更多位置安全地使用 ref 局部变量和 ref struct 类型。 可以在这些方法中安全地使用 System.ReadOnlySpan<T> 等类型。 编译器会告诉你你是否违反了安全规则。

同样,C# 13 允许迭代器方法中的 unsafe 上下文。 但是,所有 yield return 和 yield break 语句都必须处于安全上下文中。

启用 ref struct 类型来实现接口

在 C# 13 之前,不允许 ref struct 类型实现接口。 从 C# 13 开始,这些功能可以实现。 你可以声明 ref struct 类型实现某个接口。 但是,为了确保 ref 安全规则,无法将 ref struct 类型转换为接口类型。 这种转换是装箱转换,可能会违反 ref 安全性。 根据该规则,ref struct 类型无法声明用于显式实现接口方法的方法。 此外,ref struct 类型必须实现接口中声明的所有方法,包括具有默认实现的方法。

在 ref struct 类型的更新中了解详细信息。

允许在泛型中将 ref 结构类型 作为类型参数的参数。

在 C# 13 之前,无法将 ref struct 类型声明为泛型类型或方法的类型参数。 现在,泛型类型声明可以添加反约束,allows ref struct。 此反约束声明为该类型参数提供的类型参数可以是 ref struct 类型。 编译器对该类型参数的所有实例强制实施 ref 安全规则。

例如,可以声明泛型类型,如以下代码:

public class C<T> where T : allows ref struct
{
    // Use T as a ref struct:
    public void M(scoped T p)
    {
        // The parameter p must follow ref safety rules
    }
}

这样,System.Span<T> 和 System.ReadOnlySpan<T> 等类型就可以与泛型算法一起使用(如果适用)。 可以在有关 where 的更新和有关 泛型约束的编程指南文章中了解详细信息。

分部属性和索引器 现在可在 partial 类型中使用

可以在 C# 13 中声明 partial 属性和 partial 索引器。 部分属性和索引器通常遵循与 partial 方法相同的规则:创建一个 声明声明,一个_实现声明_。 两个声明的签名必须匹配。 一个限制是,不能使用自动属性声明来_实现_部分属性。 未声明正文的属性被视为_声明声明_。

public partial class C
{
    // Declaring declaration
    public partial string Name { get; set; }
}

public partial class C
{
    // implementation declaration:
    private string _name;
    public partial string Name
    {
        get => _name;
        set => _name = value;
    }
}

可以在有关部分成员的文章中了解详细信息。

重载解析优先级 允许库作者将一个重载指定为比其他重载更好

在 C# 13 中,编译器识别 OverloadResolutionPriorityAttribute,以便优先选择一个重载而不是另一个。 库作者可以使用此属性来确保首选新的更好的重载而不是现有重载。 例如,可以添加性能更高的新重载。 你不希望中断使用库的现有代码,但希望用户在重新编译时更新到新版本。 可以使用 重载解析优先级 来指示编译器应该优先选择哪个重载。 优先考虑优先级最高的超载。

此功能适用于库作者,以避免添加新重载时出现歧义。 库作者应谨慎处理此属性以避免混淆。

field 关键字

field 上下文关键字在 C# 13 中作为预览特性提供。 令牌 field 访问属性访问器中的编译器合成支持字段。 它使你可以编写访问器的主体,而无需在类型声明中显式声明备份字段。 可以为字段支持的属性的一个或两个访问器声明一个主体。

field 功能作为预览功能发布。 我们希望从你的使用经验中学习。 在还包含名为 field 的字段的类型中读取代码时,可能会出现破坏性更改或混淆。 可以使用 @field 或 this.field 来消除 field 关键字和标识符之间的歧义。

重要

field 关键字是 C# 13 中的预览功能。 必须使用 .NET 9 并将 <LangVersion> 元素设置为项目文件中 preview,才能使用 field 上下文关键字。

应小心在具有名为 field的字段的类中使用 field 关键字功能。 新的 field 关键字在属性访问器的范围内隐藏一个名为 field 的字段。 可以更改 field 变量的名称,也可以使用 @ 令牌将 field 标识符引用为 @field。 可以通过阅读 field关键字的功能规范来了解详细信息。

如果试用了此功能并有反馈,请将其添加到 csharplang 存储库中的 功能问题

本文作者:石起起

本文链接:https://www.cnblogs.com/myshiqiqi/p/18699923

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   石起起  阅读(53)  评论(0编辑  收藏  举报
评论
收藏
关注
推荐
深色
回顶
收起
点击右上角即可分享
微信分享提示