C#12那些有意思的特性

发布时间 2023-08-31 11:02:31作者: 漫思

C#12那些有意思的特性

C#在过去十年中经历了很多变化。从开源语言到新的跨平台框架,再到年度发布而不是每3 年一轮回的迭代。通过这一切,C#和.NET保持了一定的热度和流行性。在这篇博文中,将简要介绍 C# 语言设计团队面临的日常活动和挑战。你将在即将推出的 C# 12版本以及以后的版本中看到他们正在处理的内容。

为了忠于开源文化,C# 设计团队将其整个活动转移到公共 GitHub 存储库(GitHub - dotnet/csharplang: The official repo for the design of the C# programming language)中。在里面,您可以看到语言规范、新功能提案、问题、建议、问题和有价值的语言设计会议摘要(LDM csharplang/meetings at main · dotnet/csharplang · GitHub)。深入了解这些会议的内容并了解他们正在进行的讨论类型是很有趣的。这些人必须考虑编译器限制、内存和性能影响、语法挑战以及与现有 C# 代码的向后兼容性等问题。但我会把这个问题留给他们,我们只讨论结果。下面是一些即将推出的 C# 12及更高版本的最有趣的提案。

1. 主构造函数

主构造函数是 C# 12的主要功能。其主要思想是在构造函数中接收参数并将其保存为私有成员时使用更细的语法。下面是新语法的示例:

public class Person (string firstName, string lastName)
{
    string FullName => `{firstName} {lastName}`; 
}

这将与编写以下内容相同:

public class Person
{
	private string firstName;
	private string lastName;
	
	public Person(string firstName, string lastName)
	{
		this.firstName = firstName;
		this.lastName = lastName;
	}
    
    string  FullName => `{firstName} {lastName}`;
}

是不是觉得语法看起来很熟悉,那就对的,它与 C# 9中引入的record(璁板綍 - C# 鍙傝€� | Microsoft Learn)非常相似。但也有区别:

  • record是不可变的,而具有主构造函数的类将具有与常规类相同的概念用法(代码少一点)。
  • 在record中,构造函数参数保存为公共不可变属性,而在类中,它们将保存为私有字段。
  • 您可以在record中使用with关键字来创建修改的副本,但不能在具有主构造函数的类中使用。

这就是它的要点。但是如果我们仔细想想,他其实还有一些悬而未决的问题。比如当我们需要多个构造函数时会发生什么?它如何与基类一起工作?这么一看似乎语言设计并不像听起来那么容易了。感兴趣的朋友可以在官方提案中阅读所有相关信息(
csharplang/proposals/primary-constructors.md at main · dotnet/csharplang · GitHub
),并查看语言设计会议摘要LDM-2022-10-17和LDM-2023-01-18。

2. 半自动属性(和关键字field)

C#围绕属性进行了很多开发。半属性提案(
csharplang/proposals/semi-auto-properties.md at main · dotnet/csharplang · GitHub
)省去了创建支持字段的麻烦。相反,我们将能够使用新关键字field(正在提议)来访问该成员。下面是语法示例:

public class Point
{
    public int X { get { return field; } set { field = value; } }
    public int Y { get { return field; } set { field = value; } }
}

这相当于常规的自动属性

public class Point
{
    public int X { get; set; }
    public int Y { get; set; }
}

此代码是在后台为两者生成的:

public class Point
{
    private int __x;
    private int __y;
    public int X { get { return __x; } set { __x = value; } }
    public int Y { get { return __y; } set { __y = value; } }
}

使用半自动属性,我可以写这样的东西:

public class LazyInit
{
    public string Value => field ??= ComputeValue();
    private static string ComputeValue() { /*...*/ }
}

3. 基于IEnumerables的列表模式匹配

C# 12中列表模式匹配的扩展其实并没有太多优化。使用python的朋友应该对这个模式识别匹配相当熟悉,但考虑到使用c#的同学可能对此较为陌生,这似乎也就变得值得一谈了。这个功能是对列表和数组的强大模式匹配功能,包括通配符和丢弃符。在 C#12中,它从列表和数组(在C# 11中引入)扩展到任何集合。以下是一些示例:

var arr = new[] {1,2,3}; // works with arrays and lists (e.g new List<int>() {1,2,3})
Console.WriteLine(arr is [1,2,3] ); // true (list pattern)
Console.WriteLine(arr is [1,_,3] ); // true (with discard)
Console.WriteLine(arr is [1,2] ); // false
Console.WriteLine(arr is [1, ..] ); // true (slice pattern)

switch (arr) {
    case [..,3]:
        ...
        break;
    case [_,2,_]:
        ...
        break;
    default:
        ...
        break;
}

var y = arr switch {
    [1]=> "foo",
    [1,2,_] => "bar",
    _ => "zing" // default   
};

// Following doesn't work in C# 11, but will (hopefully) work in C# 12
var rng = Enumerable.Range(1,3);// 1,2,3
Console.WriteLine(rng is [1,2,3] ); // true
Console.WriteLine(rng is [1,_,3] ); // true
Console.WriteLine(rng is [1,2] ); // false
Console.WriteLine(rng is [1, ..] ); // true

4. 联合类型

联合类型之前也存在于其他语言中,比如 TypeScript。联合是一种表示变量的方法,该变量可以是多种类型之一。例如,在 TypeScript 中,您可以编写以下内容:

type BoolOrNumber = boolean | number;
const a: BoolOrNumber = false; // ok
const b: BoolOrNumber = 5; // ok
const c: BoolOrNumber = 'asdf'; // error

function Foo(x: BoolOrNumber) {
	console.log(typof x); // will be either "boolean" or "number"
}

在 C# 中,有一个提议就是这样做的。建议的语法类似于TypeScript中的语法:

A | B myUnion1 = new A(); // ok
A | B myUnion2 = new B(); // ok

public void Foo(A | B union) // also OK
{
    if(union is A a)
    {
        ...
    }
    if (union is B b)
    {
        ...
    }
}

这种联合称为“纯联合”(Pure Union)或“类型联合”(Type Union)。但是,该提案并没有包括将联合类型定义为新类型的语法。例如,我们并不能进行这种声明type BoolOrNumber = boolean | number。

这种联合类型使用起来还是非常方便的,但是也可能随之带来代码阅读上的不便。不管怎么样,如果有兴趣的朋友可以参阅Proposal: Fast, Efficient Unions · Issue #7016 · dotnet/csharplang · GitHub来了解更多。

写在最后

在这里,我们简单介绍了下一些C#潜在有趣的功能,意图让朋友们可以了解这些新功能都是如何开发出来的。

如果有兴趣了解有关即将推出的 C# 功能的更多信息,可以从查看活动语言建议开始,尽管阅读起来并不轻松。除了提案之外,还可以查看每周会议摘要和笔记。最后,还可以查看堆积如山的讨论线程和语言创意。由于它是开源的,我们甚至可以自己贡献。

对了忘记说了,如果想要尝鲜一些Preview的功能,我们可以在自己的计算机上安装Visual Studio Preview 和.Net的Preview版本(GitHub - dotnet/installer: .NET SDK Installer

最后,Happy Coding Happy Life