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. Python推荐系统库Surprise

    Surprise(Simple Python Recommendation System Engine)是一款推荐系统库,是scikit系列中的一个.简单易用,同时支持多种推荐算法.基础算法.协同过滤 ...

  2. react 中发布订阅模式使用

    react 中发布订阅模式使用 场景 怎么能将设计模式应用到我们的 React 项目中?以前一直在思考这个问题. 场景一 模块 A 模块 B 需要用到同一个数据 data,A 和 B 都会修改这份数据 ...

  3. 时间轮算法在Netty和Kafka中的应用,为什么不用Timer、延时线程池?

    大家好,我是yes. 最近看 Kafka 看到了时间轮算法,记得以前看 Netty 也看到过这玩意,没太过关注.今天就来看看时间轮到底是什么东西. 为什么要用时间轮算法来实现延迟操作? 延时操作 Ja ...

  4. APPCNA 指纹验证登录

    今天在APP中集成了指纹与手势登录功能,本文章分两部分进行记录.一是手势功能的逻辑.二是代码实现.该APP是采用APPCAN开发,直接用其已写好的插件,调用相当接口就要可以了. 1.在APP的个人中心 ...

  5. Vue.js 学习笔记之二:数据驱动开发

    在 Vue.js 框架中,与 HTML 页面元素的交互方式没有像原生 JavaScript 接口那么直接,它是通过先在 HTML 元素标签中嵌入一系列类似于普通标签属性的 Vue 指令属性来绑定数据, ...

  6. SQL实战——04. 查找所有已经分配部门的员工的last_name和first_name以及dept_no (一个逗号引发的血案)

    查找所有已经分配部门的员工的last_name和first_name以及dept_noCREATE TABLE `dept_emp` (`emp_no` int(11) NOT NULL,`dept_ ...

  7. sublime text3配置Python2、Python3的编译环境

    由于Python2.Python3使用量都很高,Python3虽然是未来趋势,但是目前个别库还是只支持Python2.所以,很多人会选择在电脑上安装两个版本的Python,那么使用sublime执行代 ...

  8. 生成器generator和迭代器Iterator

    一.列表生成式       在学习生成器迭代器之前先了解一下什么是列表生成式,列表生成式是Python内置的非常简单却强大的可以用来创建list的生成式.什么意思?举个例子,如果想生成列表[0,1,2 ...

  9. error C3861: “back_inserter”: 找不到标识符

    Reference:https://blog.csdn.net/taotaoah/article/details/52225364 and https://baike.baidu.com/item/c ...

  10. Matlab中image、imagesc和imshow函数用法解析

    来源:https://blog.csdn.net/zhuiyuanzhongjia/article/details/79621813 1.显示RGB图像 相同点:这三个函数都是把m*n*3的矩阵中的数 ...