C# 12 中新增的八大功能你都知道吗?

简介: C# 12 中新增的八大功能你都知道吗?

前言

转眼之间C#都已经更新到了12了,那么C# 12 中新增的八大功能你都了解过吗?今天我们来简单介绍一下C# 12 中新增的八大功能。

同学们可以使用最新的 Visual Studio 2022 版本或 .NET 8 SDK 尝试这些功能。

一、主构造函数

在 Visual Studio 2022 版本 17.6 预览版 2 中引入。

从 C# 12 开始,可以在类和结构中声明主构造函数。主构造函数参数都在类的整个主体的范围内。为了确保显式分配所有主构造函数参数,所有显式声明的构造函数都必须使用 this() 语法调用主构造函数。将主构造函数添加到 class 可防止编译器声明隐式无参数构造函数。在 struct 中,隐式无参数构造函数初始化所有字段,包括 0 位模式的主构造函数参数。

主构造函数参数的最常见用途包括:

  • 作为 base() 构造函数调用的参数。
  • 初始化成员字段或属性。
  • 引用实例成员中的构造函数参数。

代码示例

将任何参数放在类型名称后面的括号中:

public class NameParameter(string name)
{
    public string Name => name;
}

以下代码初始化从主构造函数参数计算的两个只读属性:

public readonly struct Distance(double dx, double dy)
{
    public readonly double Magnitude { get; } = Math.Sqrt(dx * dx + dy * dy);
    public readonly double Direction { get; } = Math.Atan2(dy, dx);
}

二、集合表达式

在 Visual Studio 2022 版本 17.7 预览版 5 中引入。

集合表达式引入了一种新的简洁语法,用于创建常用集合值。可以使用展开运算符(..)将其他集合内联到这些值中。

下面的示例展示了集合表达式的用法:

// Create an array
int[] array = [55, 99, 100, 33];
// Create a list
List<string> list = ["one", "two", "three", "five", "追逐时光者"];
// Create a span
Span<char> c = ['a', 'b', 'c', 'd', 'e', 'f', 'h', 'i', 'k'];
// Create a jagged 2D array
int[][] two2D = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [88, 8, 9]];

展开运算符(..)示例代码:

展开运算符(集合表达式中的 ..)可将其参数替换为该集合中的元素。参数必须是集合类型。以下示例演示了展开运算符的工作原理:

int[] item0 = [88, 2, 3];
int[] item1 = [22, 5, 6];
int[] item2 = [7, 99, 9];
int[] single = [.. item0, .. item1, .. item2];
foreach (var element in single)
{
    Console.Write($"{element}, ");
}

没有.. 会有异常:

正常输出:

三、内联数组

在 Visual Studio 2022 版本 17.7 预览版 3 中引入。

运行时团队和其他库作者使用内联数组来提高应用程序的性能。通过内联数组,开发人员可以在结构类型中创建固定大小的数组。具有内联缓冲区的结构体应具有与不安全固定大小缓冲区类似的性能特性。

内联数组的声明与下面的结构类似:

[System.Runtime.CompilerServices.InlineArray(20)]
    public struct Buffer
    {
        private int _element0;
    }

你可以像使用其他数组一样使用它们:

public static void Test()
        {
            var buffer = new Buffer();
            for (int i = 0; i < 20; i++)
            {
                buffer[i] = i;
            }
            foreach (var i in buffer)
            {
                Console.WriteLine(i);
            }
        }

四、Lambda 表达式中的可选参数

在 Visual Studio 2022 版本 17.5 预览版 2 中引入。

可以为 Lambda 表达式的参数定义默认值。语法和规则与将参数的默认值添加到任何方法或本地函数相同。

如果 lambda 表达式只有一个输入参数,则括号是可选的:

Func<double, double> cube = x => x * x * x;

两个或更多输入参数使用逗号加以分隔:

Func<int, int, bool> testForEquality = (x, y) => x == y;

可以显式指定类型,如下面的示例所示:

注意:输入参数类型必须全部为显式或全部为隐式;否则,便会生成 CS0748 编译器错误!!

Func<int, string, bool> isTooLong = (int x, string s) => s.Length > x;

五、ref readonly参数

在 Visual Studio 2022 版本 17.8 预览版 2 中引入。

ref readonly修饰符表示方法希望参数是一个变量,而不是一个非变量的表达式。不是变量的表达式包括常量、方法返回值和属性。如果参数不是变量,编译器会发出警告。

六、任何类型的别名

在 Visual Studio 2022 版本 17.6 预览版 3 中引入。

可以使用 using alias 指令来别名任何类型,而不仅仅是命名类型。也就是说,你可以为元组类型、数组类型、指针类型或其他不安全类型创建语义别名。

使用 using 关键字为元组类型创建别名,并进行调用:

using PointTest = (int x, int y);
namespace Csharp12
{
    internal class Class1
    {
        public static void Test()
        {
            PointTest point = (10, 20);
            Console.WriteLine($"Point coordinates: X={point.Item1}, Y={point.Item2}");
        }
    }
}

七、Experimental属性

在 Visual Studio 2022 版本 17.7 预览版 3 中引入。

  • 可以使用 System.Diagnostics.CodeAnalysis.ExperimentalAttribute 来标记类型、方法或程序集,以指示实验性特征。如果访问使用 ExperimentalAttribute 注释的方法或类型,编译器将发出警告。用 Experimental 特性标记的程序集中包含的所有类型都是实验性的。

示例代码:

namespace Csharp12
{
    [AttributeUsage(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Delegate | System.AttributeTargets.Enum | System.AttributeTargets.Event | System.AttributeTargets.Field | System.AttributeTargets.Interface | System.AttributeTargets.Method | System.AttributeTargets.Module | System.AttributeTargets.Property | System.AttributeTargets.Struct)]
    public class ExperimentalAttribute : Attribute
    {
        public ExperimentalAttribute()
        {
        }
    }
    [Experimental]
    public class ExperimentalClass
    {
        public void DoSomething()
        {
            Console.WriteLine("Doing something experimental...");
        }
    }
    internal class Class1
    {
        public static void Test()
        {
            ExperimentalClass exp = new ExperimentalClass();
            exp.DoSomething();
        }
    }
}

八、拦截器

预览功能在 Visual Studio 2022 版本 17.7 预览版 3 中引入。

拦截器是一种方法,该方法可以在编译时以声明方式将对可拦截方法的调用替换为对其自身的调用。通过让拦截器声明所拦截调用的源位置,可以进行这种替换。拦截器可以向编译中(例如在源生成器中)添加新代码,从而提供更改现有代码语义的有限能力。

注意:拦截器是一项试验性功能,在 C# 12 的预览模式下提供。在将来的版本中,该功能可能会发生中断性变更或被删除。因此,不建议将其用于生产或已发布的应用程序。

要使用拦截器,用户项目必须指定 <InterceptorsPreviewNamespaces> 属性。这是允许包含拦截器的命名空间列表。

<InterceptorsPreviewNamespaces>$(InterceptorsPreviewNamespaces);Microsoft.AspNetCore.Http.Generated;MyLibrary.Generated</InterceptorsPre
相关文章
|
7月前
|
C#
【C#】 如何实现文本框历史记录提示功能
【C#】 如何实现文本框历史记录提示功能
111 0
|
7月前
|
监控 API 开发工具
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK获取每张图像的微秒时间和FrameID功能(C#)
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK获取每张图像的微秒时间和FrameID功能(C#)
92 0
|
7月前
|
数据采集 API 开发工具
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用ForceIP强制修改网口IP功能(C#)
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用ForceIP强制修改网口IP功能(C#)
58 0
|
7月前
|
编解码 监控 开发工具
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用Binning像素合并功能(C#)
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用Binning像素合并功能(C#)
56 0
|
16天前
|
开发框架 C# iOS开发
基于C#开源、功能强大、灵活的跨平台开发框架 - Uno Platform
基于C#开源、功能强大、灵活的跨平台开发框架 - Uno Platform
|
16天前
|
网络协议 Unix Linux
精选2款C#/.NET开源且功能强大的网络通信框架
精选2款C#/.NET开源且功能强大的网络通信框架
|
2月前
|
监控 前端开发 安全
C#一分钟浅谈:文件上传与下载功能实现
【10月更文挑战第2天】在Web应用开发中,文件的上传与下载是常见需求。本文从基础入手,详细讲解如何在C#环境下实现文件上传与下载。首先介绍前端表单设计及后端接收保存方法,使用`&lt;input type=&quot;file&quot;&gt;`与`IFormFile`接口;接着探讨错误处理与优化策略,如安全性验证和路径管理;最后讲解文件下载的基本步骤,包括确定文件位置、设置响应头及发送文件流。此外,还提供了进阶技巧,如并发处理、大文件分块上传及进度监控,帮助开发者构建更健壮的应用系统。
124 15
|
2月前
|
开发框架 Cloud Native .NET
10 个 C# 关键字和功能
10 个 C# 关键字和功能
54 8
|
7月前
|
编译器 C# 开发工具
C# 12 中新增的几大功能你都知道吗?
C# 12 中新增的几大功能你都知道吗?
|
2月前
|
物联网 C#
【C#】简单的蓝牙通讯功能实现
【C#】简单的蓝牙通讯功能实现
44 0