C# 的发展是一个持续的过程,它将语言的性能、生产力和性能推向新的高度。随着 C# 12 的发布,开发人员将体验到一系列新功能和增强功能,这些功能和增强功能将塑造 C# 编程的未来。这篇博文将深入探讨 C# 12 的主要功能,强调它们的重要性,并深入了解它们的实际应用。让我们开始吧!
为了掌握主要构造函数的本质,让我们首先回顾一下 C# 9 → 中引入的现有功能。records
在 C# 9 中,开发人员获得了创建记录的能力,这些记录本质上是具有常见方案的默认实现的类。例如,使用“name”属性声明记录“user”可以方便地实例化和利用:
public record User(string Name);
// Usage
var user = new User("Atakan");
此记录功能简化了创建具有属性的类的过程。但是,在 C# 12 中,主构造函数将这种便利扩展到传统类。请考虑以下示例,其中使用 和 参数声明类:Usernameage
public class User(string name, int age)
{
public string Name// Name used directly in function members
{
get => name;
set => name= value ?? throw new ArgumentNullException(nameof(name));
}
public int Age {get; set;} = age; // name used for initialization
}
在上面的例子中,构造函数的参数和可以用于类的不同目的。nameage
C# 12 中的主要构造函数功能允许在各种上下文中使用,从而提供了灵活性。主构造函数简化了代码并增强了代码的可维护性,无论是应用于属性、方法还是构造函数。例如,可以在方法中使用主构造函数参数:name
// Primary Constructor
public class User(string name)
{
public void Method1()
{
/* Utilizing the 'name' parameter as a private field - not readonly
So, you can assign a value to it */
name = "Atakan";
Console.WriteLine(name);
}
}
C# 12 中的主要构造函数标志着朝着简化代码和改进开发人员体验迈出的重要一步。开发人员在使用它们时需要注意以下几点:
C# 12 版本引入了一项称为集合表达式的突破性功能。此增强功能彻底改变了数组和其他数据结构的初始化,为开发人员提供了更简洁、更具表现力的语法。
传统上,在 C# 中声明和初始化数组涉及冗长的语法,如下所示:
int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8};
集合表达式功能使开发人员能够使用更简洁的语法实现相同的结果:
int[] numbers = [1, 2, 3, 4, 5, 6, 7, 8];
这种语法不仅增强了可读性,而且为数组初始化带来了统一性。但是,需要注意的是,显式类型声明现在是强制性的,这意味着您不能将关键字与此新功能一起使用!var
集合表达式的强大功能超越了数组,涵盖了各种数据结构。例如,初始化一个跨度或一个锯齿状的 2D 数组变得更加直观:
Span<int> span = ['a', 'b', 'c'];
int[][] jaggedArray = [[1, 2, 3], [4, 5, 6]];
奖金→空字典初始化
虽然不是计划中的 C# 12 功能的正式组成部分,但开发人员能够使用尖括号初始化空字典。
Dictionary<string, string> dic = [];
RefReadonly 参数是 C# 12 中的一项新功能,它允许您传递对不应修改的数据的引用。这可以提高性能并使代码更具可读性。将对变量的引用作为参数传递时,编译器将确保变量的值不能在方法内部更改。这意味着您可以安全地将引用传递给方法,而不必担心该方法会修改变量的值。ref readonly
public void Swap(ref readonly int x, ref readonly int y)
{
int temp = x;
x = y;
y = temp;
}
在 blow 示例中,该方法采用两个参数:和 。修饰符指示该方法不能修改 和 的值。在方法中,使用临时变量交换 和 的值。这确保了 和 的原始值保持不变。Swapref readonlyxyref readonlyxyxyxy
即将推出的 C# 12 版本引入了一项备受期待的生活质量功能,称为默认 Lambda 参数。此功能允许开发人员设置参数的默认值、简化代码和简化调用,从而增强了 lambda 表达式的灵活性。
考虑一个 lambda 表达式定义参数的场景,如下例所示:
var ageLambda = (string name, int age) => $"{name} is {age} years old";
传统上,在调用此 lambda 时,必须显式提供这两个参数:
string result = ageLambda("Atakan", 40);
默认 Lambda 参数使开发人员能够在 lambda 表达式中设置参数的默认值:
var ageLambdaWithDefault = (name = "Atakan" , age = 40) => $"{name} is {age} years old";
string result = ageLambdaWithDefault();
// I can also specify any value, for e.g. --> ageLambdaWithDefault("Korez", 35);
此功能通过放宽指令使用规则来挑战传统约束,尤其是在指针类型、数组类型等的上下文中。using alias
Alias Any Type 实质上重新定义了 C# 12 中指令的可能性。以前在某些上下文(如指针类型和数组类型)中受到限制,Alias Any Type 打破了这些障碍,开创了类型定义灵活性的新时代。using alias
Alias Any Type 的变革能力的一个说明性示例是创建 2D 点类型。使用以下声明:
using Point2D = int X, int Y;
开发人员现在可以用作简洁的元组式结构,让人联想到结构:Point2D
var point = new Point2D(3, 7);
这为隐式转换开辟了可能性,使开发人员能够无缝集成到他们的代码库中。Point2D
在优化性能的最新进展中,C# 12 引入了一项称为内联数组的功能。此功能最初由 Microsoft 的运行时团队和库作者使用,现在已公开,以使更广泛的开发人员受益。
主要目的是提高利用 .NET 或关联库的应用程序的性能。因此,内联阵列通过固定大小的堆栈分配缓冲区提供高性能解决方案。_内联数组_的声明类似于以下内容:struct
[System.Runtime.CompilerServices.InlineArray(10)]
public struct Buffer
{
private int _element0;
}
您可以像使用任何其他数组一样使用它们:
var buffer = new Buffer();
for (int i = 0; i < 10; i++)
{
buffer[i] = i;
}
foreach (var i in buffer)
{
Console.WriteLine(i);
}
内联数组通过为开发人员提供固定大小的堆栈分配缓冲区来解决性能问题。关键目标是使堆栈分配的缓冲区的性能特征与未保存的固定大小缓冲区的性能特征保持一致。虽然内部工作原理可能会深入研究性能优化的复杂细节,但开发人员可以利用内联数组来提高代码的速度和效率。
此属性为开发人员提供了一种将功能标记为实验性或风险功能的机制,以指示将来更新中的潜在更改或删除。它用作被视为实验性或风险的特征的标记。通过将此属性应用于特定功能或代码块,开发人员表示关联的功能需要接受评估,并且可能会在将来的更新中进行更改或删除。
若要将功能指定为实验性功能,开发人员可以通过提供诊断 ID 来利用实验属性。下面是一个简单的插图:
[Experimental("RiskyID")]
public class ExperimentalFeature
{
// Feature implementation
}
当尝试使用标记的功能时,开发人员会收到一个编译错误,强调代码的实验性质:
// Compilation error due to experimental feature
var instance = new ExperimentalFeature();
若要继续使用实验性功能,开发人员必须显式禁止显示编译错误。此有意步骤表明您意识到与该功能相关的风险:
#pragma warning disable RiskyId
var instance = new ExperimentalFeature();
#pragma warning restore RiskyId
C# 12 引入了一项名为**“拦截器**”的革命性功能,使开发人员能够在编译时截获和修改方法调用。虽然处于预览状态,但此功能为代码操作打开了新的大门,而无需直接更改源代码。
侦听器允许开发人员在编译时截获方法调用并将其替换为自定义代码。这种强大的功能在代码操作中引入了范式转变,使开发人员能够增强或修改行为,而无需直接修改原始源代码。
请考虑以下具有两种方法的示例类:
public class Example
{
public void MethodOne() => Console.WriteLine("Hello from method one");
public void MethodTwo(string name) => Console.WriteLine($"Hello from method two, {name}");
}
现在,让我们创建一个 Interceptor 来修改以下行为:MethodOne
[InterceptsLocation("C:\\Path\\To\\Your\\File\\Example.cs", 6, 9)]
public static class Interception
{
public static void InterceptMethodOne(this Example example)
{
Console.WriteLine("Hello from Interceptor");
}
}
在此示例中,扩展方法在源代码中的指定位置截获原始内容。InterceptMethodOneMethodOne
要使用 Interceptor,不需要对原始类进行任何修改。只需实例化类并像往常一样调用方法:Example
class Program
{
static void Main()
{
Example example = new Example();
example.MethodOne(); // Outputs: Hello from Interceptor
example.MethodTwo("Atakan"); // Outputs: Hello from method two, Atakan
}
}
侦听器还可以处理方法参数。例如,使用 Interceptor 进行修改:MethodTwo
[InterceptsLocation("C:\\Path\\To\\Your\\File\\Example.cs", 7, 9)]
public static class Interception
{
public static void InterceptMethodTwo(this Example example, string name)
{
Console.WriteLine($"Hello from Interceptor, {name}");
}
}
现在,调用会触发拦截器:MethodTwo
class Program
{
static void Main()
{
Example example = new Example();
example.MethodTwo("Atakan"); // Outputs: Hello from Interceptor, Atakan
}
}
C# 12 标志着 C# 语言发展的一个重要里程碑,它带来了大量的新功能和增强功能,使开发人员能够编写更具表现力、可维护性和高性能的代码。从使用主构造函数的简化对象初始化到使用内联数组创建简洁的数组,C# 12 引入了一系列可提高工作效率和代码质量的功能。
我鼓励您深入研究激动人心的 C# 12 世界,并探索它为制作出色代码提供的无限机会。当你踏上这一发现之旅时,请记住,C# 社区始终在这里为你提供支持和指导。让我们一起拥抱 C# 12 的强大功能,塑造软件开发的未来。