C# 中的只读结构体(readonly struct)
翻译自 John Demetriou 2018年4月8日 的文章 《C# 7.2 – Let’s Talk About Readonly Structs》[1]
在本文中,我们来聊一聊从 C# 7.2 开始出现的一个特性 readonly struct。
任一结构体都可以有公共属性、私有属性访问器等等。我们从以下结构体示例来开始讨论:
public struct Person
{
public string Name { get; set; }
public string Surname { get; set; }
public int Age { get; set; }
public Person(string name, string surname, int age)
{
Name = name;
Surname = surname;
Age = age;
}
public void Replace(Person other)
{
this = other;
}
}
如您所见,所有属性都可以公开访问和修改。更糟糕的是,我们甚至可以访问 this (通过调用 Replace 方法),将其更改为同一结构体类型的另一个实例。
这就是 readonly 关键字出现的原因。如果(仅)在结构体的定义中添加它,如下所示:
public readonly struct Person
{
public string Name { get; set; }
public string Surname { get; set; }
public int Age { get; set; }
public Person(string name, string surname, int age)
{
Name = name;
Surname = surname;
Age = age;
}
public void Replace(Person other)
{
this = other;
}
}
编译器会显示如下面截图中的错误提示:

为什么会这样?这是因为当我们向结构体定义添加 readonly 关键字,其实是把每个属性都设置为只读的了,包括 this 的值。
要让代码通过编译的唯一方法是把所有内容都设置为只读的,也就是说我们的结构体应该像这样:
public readonly struct Person
{
public string Name { get; }
public string Surname { get; }
public int Age { get; }
public Person(string name, string surname, int age)
{
Name = name;
Surname = surname;
Age = age;
}
}
因此,添加 readonly 可以消除结构体实例内部或外部发生意外赋值或修改值的可能性。不过,需要注意的一件事是,如果您经常使用无参构造函数并给属性赋值,像这样:
Person s = new Person();
//错误
s.Age = 15;
s.Name = "asd";
s.Surname = "qwe";
或者像这样:
//错误
Person s = new Person
{
Age = 15,
Name = "asd",
Surname = "qwe"
};
虽然此结构体的默认无参构造函数仍然可以调用,但给任何属性赋值都将引发编译错误,因为属性是只读的。
实际上,对此结构体的无参构造函数的调用会将其所有属性设置为它们的默认值,而且在结构体实例的整个生命周期中,永远不会被修改。
正确的初始化方法是调用参数化构造函数:
Person s = new Person("asd", "qwe", 15);
总之,这将有助于更容易地表明您的意图,因为您可以从一开始就定义这个结构体是不可变和不可修改的。
译者总结
使用 readonly 修饰符声明 struct 的目的就是为了明确地声明一个不可变的值类型。
readonly 结构体的所有数据成员都必须是只读的:
- 所有字段声明都必须具有
readonly修饰符 - 所有属性(包括自动实现的属性)都必须是只读的
这就保证了 readonly 结构体的成员不会修改该结构体的状态。在 C# 8.0 及更高版本中,除构造函数外的其他实例成员都是隐式 readonly 的。
作者 : John Demetriou
译者 : 技术译民
出品 : 技术译站
链接 : 英文原文
https://www.devsanon.com/c/c-7-2-lets-talk-about-readonly-structs/ C# 7.2 – Let’s Talk About Readonly Structs ︎
C# 中的只读结构体(readonly struct)的更多相关文章
- Swift中元组(Tuples),结构体(Struct),枚举(Enums)之间的区别
Swift有许多种存储数据方式,你可以用枚举(enums),元组(tuples),结构体(structs),类(classes),在这篇文章中我们将比较枚举.元组.结构体之间区别,首先从最简单的开始- ...
- C语言结构体(struct)常见使用方法
基本定义:结构体,通俗讲就像是打包封装,把一些变量有共同特征(比如同属于某一类事物的属性)的变量封装在内部,通过一定方法访问修改内部变量. 结构体定义: 第一种:只有结构体定义 struct stuf ...
- MFC中的NMHDR结构体和NMUPDOWN结构体
建立spin控件,创建UDN_DELTAPOS一个消息函数后: void CSpinDlg::OnDeltaposSpin1(NMHDR* pNMHDR, LRESULT* pResult) { NM ...
- Go语言基础之8--面向对象编程1之结构体(struct)
一.结构体详解 1.1 声明和定义 1.Go中面向对象是通过struct来实现的, struct是用户自定义的类型 2.Go 语言中数组可以存储同一类型的数据,但在结构体中我们可以为不同项定义不同的数 ...
- 剔除list中相同的结构体数据
剔除list中相同的结构体数据,有三个思路:1.两层循环,逐个比较 2.使用set容器来剔除 3.使用unique方法去重 // deduplication.cpp : 定义控制台应用程序的入口点. ...
- 如何系统学习C 语言(中)之 结构体篇
1,结构体 在前面我们知道变量和数组都可以用来存储数据,变量用来存储单个数据,数组可以用来存储一组同类型的数据,但你有没有发现--它们都只适合单一属性的数据.那现实生活中,很多对象都是具有多属性的.例 ...
- C语言中 不定义结构体变量求成员大小
所谓的求成员大小, 是求成员在该结构体中 用 sizeof(结构体名.结构体成员名) 求来的. 很多时候我们需要知道一个结构体成员中的某个成员的大小, 但是我们又不需要定义该结构体类型的变量(定义的话 ...
- C 语言实例 - 使用结构体(struct)
C 语言实例 - 使用结构体(struct) C 语言实例 C 语言实例 使用结构体(struct)存储学生信息. 实例 #include <stdio.h> struct student ...
- 【2016-08-18】转载:总结C++中几种结构体初始化的方法
作者:Ac_Von 博客地址:http://www.cnblogs.com/vongang/ 文章地址:http://www.cnblogs.com/vongang/archive/2011/07/3 ...
随机推荐
- Java中的常见锁(公平和非公平锁、可重入锁和不可重入锁、自旋锁、独占锁和共享锁)
公平和非公平锁 公平锁:是指多个线程按照申请的顺序来获取值.在并发环境中,每一个线程在获取锁时会先查看此锁维护的等待队列,如果为空,或者当前线程是等待队列的第一个就占有锁,否者就会加入到等待队列中,以 ...
- Maven【常见知识点速查】
文章更新时间:2020/04/10 一.为什么使用Maven这样的构建工具[why] ① 一个项目就是一个工程 如果项目非常庞大,就不适合使用package来划分模块,最好是每一个模块对应一个工程,利 ...
- 优酷kux转mp4
利用YouKu客户端下载的视频格式为kux,只能通过YouKu客户端播放,很不方便.在网上看到有人通过ffmpeg解码器进行转换,写成了批处理,如下: @echo off setlocal enabl ...
- Windows下设置Mongodb用户名密码
MongoDB认证: 在默认的情况下,Mongodb是监听在127.0.0.1 IP上的,端口号默认为27017,任何客户端都可以连接,不需要认证 默认情况下,Mongodb也是没有管理账户的,除非你 ...
- 智慧矿山-选矿工艺数字 3D 可视化
前言 现代科技和工业的发展对矿物原料的要求越来越高,直接开采的原矿石往往达不到标准,而原矿通过选矿加工后则可以满足要求.选矿技术在冶金.煤炭.化工.建材和环保等部门都得到应用,对国民经济的发展意义重大 ...
- springboot集成swagger文档
//此处省略springboot创建过程 1.引入swagger相关依赖(2个依赖必须版本相同) <dependency> <groupId>io.springfox</ ...
- VS2015中无法查找或打开 PDB 文件
装载:https://blog.csdn.net/aalonso/article/details/90672072 MFCApplication1.exe"(Win32): 已加载" ...
- Apache账户密码加密方式介绍
一.apache密码存储格式 apache的用户密码一般会生成保存在.htpasswd文件中,保存路径由用户创建时确定,根据使用加密算法有五种保存格式: [注]:如果用户指定了保存密码的文件名,视用户 ...
- 配置adpate的方式
配置adpate的方式 资源文件配置 ArryAdapter<CharSequence>cadapt= ArryAdapter.createFromResource(this,资源id,a ...
- Navicat连接MySQL报错-2059
解释原因:据说,mysql8 之前的版本中加密规则是mysql_native_password,而在mysql8之后,加密规则是caching_sha2_password, 解决问题方法有两种,一种是 ...