欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C# 9.0 新特性预览 - 类型推导的 new

程序员文章站 2022-05-27 18:49:38
随着 .NET 5 发布日期的日益临近,其对应的 C# 新版本已确定为 C# 9.0,其中新增加的特性(或语法糖)也已基本锁定,本系列文章将向大家展示它们。 ......

c# 9.0 新特性预览 - 类型推导的 new

前言

随着 .net 5 发布日期的日益临近,其对应的 c# 新版本已确定为 c# 9.0,其中新增加的特性(或语法糖)也已基本锁定,本系列文章将向大家展示它们。

目录

[c# 9.0 新特性预览 - 类型推导的 new]
[c# 9.0 新特性预览 - lambda 中的弃元]
[c# 9.0 新特性预览 - 更简便的空参数检查]
[c# 9.0 新特性预览 - record 类型]
[c# 9.0 新特性预览 - 模式匹配的改善]
[c# 9.0 新特性预览 - 其他小的变化]

具有类型推导的 new 表达式 (target-typed new expressions)

这是一个本应随着 c# 8.0 发布的语言特性,但因种种原因在发布 c# 8.0 的最后关头,它被移出了最终的发布版本,下面我们来认识认识它。
大家都知道,c# 在3.0中新增 var 关键字来做隐式类型声明,把繁重的声明语法简化了。

dictionary<string, list<int>> field = new dictionary<string, list<int>>()
// 可以简化为
var field = new dictionary<string, list<int>>()

var 关键字的基本原理不再复述,简单说就是编译器可以根据等号后面的类型推导出 var 的类型,那么是不是也可以反过来,我们先声明类型,接下来的 new 关键字后面就不用写类型了呢?于是本文介绍的特性来了:

dictionary<string, list<int>> field = new dictionary<string, list<int>>()
// c# 9.0 中可以写成
dictionary<string, list<int>> field = new()

从以上代码可以看出语法很简单,即省略了繁琐的可以推导出的类型。
其语法 spec 如下:

'new' '(' argument_list? ')' object_or_collection_initializer?

搭配初始化器,我们可以进一步简化带有初始值的初始化。

dictionary<string, list<int>> field = new() {
    { "item1", new() { 1, 2, 3 } }
};

进一步展示该语法在各种情况下的使用

在所有可以推导出类型的上下文中,都可以使用,例如:

xmlreader.create(reader, new() { ignorewhitespace = true });

带有参数的构造方法:

class c {
    c(params int[] p) {}
}

c c = new(1, 2, 3);

调用方法时:

class a {}
static void m(a a) {};

m(a: new());

配合对象初始化器:

x x = new() { field = 42 };

泛型的类型推导,需要注意,要有一个显示类型声明才能正确推导:

void m<t>(t t1, t t2) {}

m(new x(), new());

类似的,数组的声明

var arr = new[] {new x(), new()};

不适用此特性的场景

值类型的初始化,可以使用 default 替代

int x = new(); // error
struct y = new(); // error

使用 as 操作时无法正确推导

console.write(new() as x); // error

自然,使用 var 时也无法推导

var x = new(); // error

有歧义的重载

void m(object a, x b) => console.write($"{a} {b}");
void m(x a, object b) => console.write($"{a} {b}");

m(new(), new()); // error

需要注意的地方

这个新语法 new(),比较容易与匿名类型语法混淆 new{},它们两个是完全不同的东西,需要注意一下。

参考

[proposal: target-typed new expressions]
[unit test: targettypednewtests.cs]