C# 9.0 新特性预览 - init-only 属性

前言

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

目录

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

[C# 9.0 新特性预览 - 空参数校验]

[C# 9.0 新特性预览 - 顶级语句]

[C# 9.0 新特性预览 - init-only 属性]

[C# 9.0 新特性预览 - Record 类型]

[C# 9.0 新特性预览 - 模式匹配的改善]

[C# 9.0 新特性预览 - 源代码生成器]

[C# 9.0 新特性预览 - 其他小的变化]

只初始化 setter (Init Only Setters)

这个特性允许创建只初始化(init only)的属性和索引器,使得 C# 中的不可变模型更加灵活。

背景

在此之前,我们创建实体类/POCO类/DTO类等等模型类的时候,都期望属性只读不允许从外部修改,会将属性的 setter 设为私有或者干脆不设置 setter,例如:

public class Person
{
public string Name { get; private set; }
// OR
//public string Name { get; }
}

再添加一个拥有全部属性作为签名的构造方法:

...
public Person(string name)
{
this.Name = name;
}
...

这样做虽然可以达到目的,但是带来了两个问题

1.假如属性增多,会带来工作量的成倍增加,以及不易维护

2.无法使用对象初始化器(object initializers)

var person = new Person
{
Name = "Rwing" // Compile Error
};

在这个情况下,init 关键字应运而生了。

语法

语法很简单,只需要将属性中的 set 关键字替换为 init 即可:

public string Name { get; init; }

以上代码会被大致翻译为:

private readonly string _name;
public string Name
{
get { return _name; }
set { _name = value;}
}

可以看到,与 set 的区别是,init 会为背后的字段添加 readonly 关键字。

这样我们就可以去掉一堆属性的构造方法转而使用对象初始化器了,并且达到了不可变的目的。

var person = new Person
{
Name = "Rwing"
};
// 初始化后无法再次修改
person.Name = "Foo"; // Error: Name is not settable

这一语法,有很多场景需要配合同样在 C# 9.0 中新增的 record 类型使用。

哪些情况下可以被设置

  • 通过对象初始化器
  • 通过 with 表达式
  • 在自身或者派生类的构造方法中
  • 在标记为 init 的属性中
  • 在特性(attribute)类的命名参数属性中

以上场景不难理解,但是值得一提的是,只有 get 的属性是不可以派生类的构造方法中赋值的,但是 init 可以:

class Base
{
public bool Foo { get; init; }
public bool Bar { get; }
} class Derived : Base
{
Derived()
{
Foo = true;
Bar = true; // ERROR
}
}

此外有一种例外, 在以上场景中的 lambda 或本地函数中,也不允许被设置,例如:

原因也很简单,lambda 或本地函数在编译后已经不在构造函数中了。

public class Class
{
public string Property { get; init; } Class()
{
System.Action a = () =>
{
Property = null; // ERROR
};
local();
void local()
{
Property = null; // ERROR
}
}
}

参考

[Proposal: Init Only Setters]

[InitOnlyMemberTests.cs]

C# 9.0 新特性预览 - init-only 属性的更多相关文章

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

    C# 9.0 新特性预览 - 类型推导的 new 前言 随着 .NET 5 发布日期的日益临近,其对应的 C# 新版本已确定为 C# 9.0,其中新增加的特性(或语法糖)也已基本锁定,本系列文章将向大 ...

  2. C# 9.0 新特性预览 - 空参数校验

    C# 9.0 新特性预览 - 空参数校验 前言 随着 .NET 5 发布日期的日益临近,其对应的 C# 新版本已确定为 C# 9.0,其中新增加的特性(或语法糖)也已基本锁定,本系列文章将向大家展示它 ...

  3. C# 9.0 新特性预览 - 顶级语句

    C# 9.0 新特性预览 - 顶级语句 前言 随着 .NET 5 发布日期的日益临近,其对应的 C# 新版本已确定为 C# 9.0,其中新增加的特性(或语法糖)也已基本锁定,本系列文章将向大家展示它们 ...

  4. Vue.js 3.0 新特性预览

    总结起来,Vue 3 以下方面值得我们期待 : 更快 更小 更易于维护 更多的原生支持 更易于开发使用 完整的PPT:docs.google.com/presentatio… Evan 和 Vue 团 ...

  5. avalon1.3的新特性预览

    avalon1.2的性能优化风暴很快就告一段落,入职也快一个月了,许多乱七八糟的事也少了下来,估计未来一个月会有许多好东呈现给大家. 首先是一个性能检测工具.由于MVVM是将原本由人脑干的事,转到各种 ...

  6. Windows Phone 8.1SDK新特性预览

    前言    Windows Phone 8.1的预览版将在近期推送,WP 8.1的SDK也已经进入到RC阶段,可以从这里安装.本次更新的SDK被直接集成到了VS2013Update2里面,不再是单独的 ...

  7. Office 2016 正式发布——新特性预览

    今天微软又发生了一件大事!Windows Office 2016正式发布,这标志着Windows Office 又达到了一个新的里程碑! 全新的Office 发布为Office 365 用户带来了新的 ...

  8. CSS3_新特性预览

    一.强大的CSS选择器 以前我们通常用class. ID 或 tagname 来选择HTML元素,CSS3的选择器强大的难以置信.  它们可以减少在标签中的class和ID的数量更方便的维护样式表.更 ...

  9. C# 7.0 新特性2: 本地方法

    本文参考Roslyn项目中的Issue:#259. 1. C# 7.0 新特性1: 基于Tuple的“多”返回值方法 2. C# 7.0 新特性2: 本地方法 3. C# 7.0 新特性3: 模式匹配 ...

随机推荐

  1. B树【Balanced-Tree】

    一.引言 B树是二叉平衡树的一个变种,在学习之前,我们先了解一下二分法,二叉树的一些相关的基本概念,有助于我们更好的理解B树~ 二.二叉树 定义:二叉树即二叉平衡树 意义:通过二分法来进行元素查找,时 ...

  2. 【性能监控-Perfmon工具】手动添加数据收集器,点击保存时需要输入用户NT AUTHORITY\SYSTEM的密码问题

    发现是有的电脑会弹出这种输入用户NT AUTHORITY\SYSTEM密码的现象,有的电脑不会弹出这个对话框.......仍然没搞懂是为什么? 关键是输入windows用户登录时的密码也不对!!压根不 ...

  3. Tomcat 中 catalina.out、catalina.log、localhost.log 和 access_log 的区别

    打开 Tomcat 安装目录中的 log 文件夹,我们可以看到很多日志文件,这篇文章就来介绍下这些日记文件的具体区别. catalina.out 日志 catalina.out 日志文件是 Tomca ...

  4. C++雾中风景15:聊聊让人抓狂的Name Mangling

    Name Mangling,直接翻译过来为名字改写 .它是深入理解 C++ 编译链接模型的必由之路. 笔者近期进行数据库开发工作时,涉及到MySQL客户端的编译链接的问题,通过重新厘清了之前理解一知半 ...

  5. Go-The process cannot access the file because it is being used by another process.

    where? Go程序在读取文件时候 why? 因为有其他进程也在读取和Go程序想要读取的文件,参数冲突 way? 关闭其他程序进程对该文件的读取操作

  6. safari 浏览器版本升级后提示“此网页出现问题,已重新载入网页” 解决办法

    safari回退条件 版本回退的前提是关闭电脑的SIP机制,命令行 csrutil status 检测状态.Mac os 10.14以下版本回退Safari后插件还是可以用的,升了新系统退了也没法用了 ...

  7. SQL实战——03. 查找各个部门当前(to_date='9999-01-01')领导当前薪水详情以及其对应部门编号dept_no

    查找各个部门当前(to_date='9999-01-01')领导当前薪水详情以及其对应部门编号dept_noCREATE TABLE `dept_manager` (`dept_no` char(4) ...

  8. 【git】关联本地仓库与远程仓库

    1.在远程建立一个空项目[项目名称]2.git init3.git remote add origin [git 地址]4.git pull origin master5.git push origi ...

  9. sop服务治理

    一,为什么需要服务治理: 我们最先接触的单体架构, 整个系统就只有一个工程, 打包往往是打成了 war 包, 然后部署到单一 tomcat 上面, 这种就是单体架构, 如图: 假如系统按照功能划分了, ...

  10. MeteoInfoLab脚本示例:天气现象符号

    天气现象符号分布图实际就是散点图,可以用scatterm函数绘制,但之前需要创建天气符号图例,用weatherspec函数.如果只需要绘制某些天气现象(比如雾.霾),可以给出相应的天气符号序号列表(可 ...