在C#8.0中,结构(struct)引入了一项新特性,就是使其成员支持readonly(只读),这个特性用来限制被其修饰的成员不会改变结构的内部状态。这项特性,与C#7.2版本添加的readonly struct和ref readonly方法返回、及C#原本之前的只读字段声明修饰作用一起,共同组成了目前readonly的四种修饰作用。

一、readonly只读成员的主要作用

如前所述,就是被修饰的成员不会改变或者修改结构的内部状态。

二、readonly只读成员规则与限制

  1. 只对结构(struct)的成员有效,不能用于类,指示该成员不会修改结构的内部状态。如果该成员直接修改状态或者访问未使用readonly修饰的成员,则结果会报错。

  2. 不能用于静态成员和构造函数。

  3. readonly修饰的自动属性不能有set访问器。

  4. readonly添加到属性或者索引的单个get访问器中。但同时不能在属性上有readonly修饰符

  5. readonly函数访问未标记为readonly的成员时,会发出创建防御性副本的警告。

三、Readonly只读成员的示例代码:

//(C# 8.0)结构readonly成员规则及示例:
//1. 只对结构(struct)的成员有效,不能用于类,指示该成员不会修改结构的内部状态。如果该成员直接修改状态或者访问未使用readonly修饰的成员,则结果会报错。
//2. 不能用于静态成员和构造函数。
//3. readonly修饰的自动属性不能有set访问器。
//4. readonly添加到属性或者索引的单个get访问器中。但同时不能在属性上有readonly修饰符
//5. readonly函数访问未标记为readonly的成员时,会发出创建防御性副本的警告。
public struct MutablePerson
{
//结构中静态字段即可声明也可初始化
private static readonly MutablePerson _origin = new MutablePerson(); //此属性由ref readonly返回的引用,调用方无法修改来源
public static ref readonly MutablePerson Origin => ref _origin; //ref readonly 只能用于方法或者属性,不能用于字段。
//public static ref readonly MutablePerson NewOne; // 结构中字段只能声明,不能初始化,静态字段除外
public static int Population = ;
private float _maxAge;
public string Name; //结构中自动属性只能在此声明,不能初始化。
//此自动属性不能在属性外添加readonly,因为其中含有set访问器
public int Age { get; set; }
//public readonly int Age { get; set; } public float Height {
//readonly可以添加到属性或者索引的单个get访问器中。但同时不能再给属性上有readonly修饰符
readonly get;
set; } //readonly修饰的自动属性不能有set访问器。与下面注释的代码等效
readonly public string Nationality { get;}
//public string Nationality { readonly get; }
//string _nationality;
//public string Nationality { readonly get { return _nationality; } set { } } readonly public float MaxAge{
get { return _maxAge; }
set { } // 没有用,但是合法
} ////结构中不能包含显式的无参构造函数,编译器会自动创建
//public MutablePerson()
//{
// Name = null;
// Age = 0;
// Height = 0;
//} //每个构造函数中必须对所有未初始化的字段和自动属性进行初始化
public MutablePerson(string name):this(name,)
{
Height = 0.5f;
Nationality = "CHINA";
_maxAge = ;
} //每个构造函数中必须对所有未初始化的字段和自动属性进行初始化
public MutablePerson(string name, int age):this(name,age,0.5f) =>
(Nationality,_maxAge) = ("CHINA",); //每个构造函数中必须对所有未初始化的字段和自动属性进行初始化
public MutablePerson(string name, int age, float height)
=> (Name, Age, Height, Nationality, _maxAge) = (name, age, height, "CHINA", ); public MutablePerson(MutablePerson other)
{
this = other;
} public MutablePerson Replace(MutablePerson other)
{
this = other;
return other;
} //此成员不能用readonly修饰,因为里面代码会改变成员状态。
public void Increase(int ageOffset, float heightOffset)
{
Age += ageOffset;
Height += heightOffset;
} // readonly 成员中没有对状态字段和属性的任何修改
public readonly string SayHello => $"Hello, my name is {Name}, I am {Age} and my height is {Height}"; //readonly函数访问未标记为readonly的SayHello方法时,会发出创建防御性副本的警告。
public readonly override string ToString() => $"(Name:{Name}, Age:{Age}, Height:{Height}),{SayHello}";
}

四、其他readonly struct等非8.0相关特性说明

C#7.2 readonly struct 指示结构是不可变的。有如下限制:

  1. 该结构中每个字段和属性都是readonly

  2. 需要公共构造函数初始化成员

  3. this也是readonly,只能在构造函数中进行初始化赋值

  4. 不能定义像字段样子的事件

ref readonly用来指示返回的引用,调用方无法修改来源。而readonly修饰的字段,指示该字段在被初始化后,不能再被修改。

具体示例代码如下:

//(C#7.2) readonly struct 指示结构是不可变的。有如下限制:
//1.该结构中每个字段和属性都是readonly
//2.需要公共构造函数初始化成员
//3.this也是readonly,只能在构造函数中进行初始化赋值
//4.不能定义像字段样子的事件
public readonly struct ReadonlyPerson
{
//结构中静态字段即可声明也可初始化
private static readonly ReadonlyPerson _origin = new ReadonlyPerson(); //由ref readonly返回的引用,调用方无法修改来源。注意此是个属性
public static ref readonly ReadonlyPerson Origin => ref _origin; //readonly struct对静态字段没有效用,不必指定readonly
public static int Population = ; // 必须给readonly struct中的字段指定readonly。结构中字段只能在此声明,不能初始化
public readonly string Name; //不能有set访问器,且只读自动属性指示编译器为这些属性创建readonly的支持字段。结构中自动属性只能在此声明,不能初始化
public int Age { get; } //不能有set访问器,且只读自动属性指示编译器为这些属性创建readonly的支持字段。结构中自动属性只能在此声明,不能初始化
public float Height { get; } ////结构中不能包含显式的无参构造函数,编译器会自动创建
//public ReadonlyPerson()
//{
// Name = null;
// Age = 0;
// Height = 0;
//} public ReadonlyPerson(string name):this(name,)
{
//必须在此初始化,没有参数必须初始化为默认值,不能在结构声明中初始化
Height = 0.5f;
} //每个构造函数中必须对所有未初始化的字段和自动属性进行初始化
public ReadonlyPerson(string name, int age) : this(name, age, 0.5f)
{ } //每个构造函数中必须对所有未初始化的字段和自动属性进行初始化
public ReadonlyPerson(string name, int age, float height)
=> (Name, Age, Height) = (name, age, height); public ReadonlyPerson(ReadonlyPerson other)
{
this = other;//可以用另一个对象来初始化。
} public MutablePerson Replace(MutablePerson other)
{
//this = other; //this是readonly,不能被修改。
//this.Age = other.Age;//this是readonly,他的成员也是不能被修改。
return other;
} public void Increase(int ageOffset, float heightOffset)
{
//Age += ageOffset; //Age在readonly struct中是只读的,因此在这里不能被赋值。
//Height += heightOffset; //Height在 readonly struct中是只读的,因此在这里不能被赋值。
} // 该成员中没有对状态字段和属性的任何修改
public string SayHello => $"Hello, my name is {Name}, I am {Age} and my height is {Height}"; //该函数不能给本结构中的任何字段和属性做出修改
public override string ToString() => $"(Name:{Name}, Age:{Age}, Height:{Height}),{SayHello}"; }

五、结束语

至此,有关struct相关的readonly的四种修饰及其用法的介绍就到这里,因水平有限,如有错误或不妥指出,请指正。

C#8.0中新特性之一:结构readonly成员的更多相关文章

  1. php5.3到php7.0.x新特性介绍

    <?php /*php5.3*/ echo '<hr>'; const MYTT = 'aaa'; #print_r(get_defined_constants()); /* 5.4 ...

  2. paip.php 5.0 5.3 5.4 5.5 -6.0的新特性总结与比较

    paip.php 5.0 5.3 5.4  5.5 -6.0的新特性总结与比较 PHP5的新特性 2 · 对象的参照过渡是默认的(default) 3 · 引入访问属性的限制 3 · 引入访问方法的限 ...

  3. C# 6.0/7.0 的新特性

    转眼C#语言都已经迭代到7.0版本了,很多小伙伴都已经把C# 7.0 的新特性应用到代码中了,想想自己连6.0的新特性都还很少使用,今天特意搜集了一下6.0和7.0的一些新特性,记录一下,方便查阅. ...

  4. 关于 Swift 2.0 - 语言新特性与革新

    随着刚刚结束的 WWDC 2015 苹果发布了一系列更新,这其中就包括了令人振奋的 Swift 2.0. 这是对之前语言特性的一次大幅的更新,加入了很多实用和方便的元素,下面我们就一起来看看这次更新都 ...

  5. 相比于python2.6,python3.0的新特性。

    这篇文章主要介绍了相比于python2.6,python3.0的新特性.更详细的介绍请参见python3.0的文档. Common Stumbling Blocks 本段简单的列出容易使人出错的变动. ...

  6. Atitit jquery  1.4--v1.11  v1.12  v2.0  3.0 的新特性

    Atitit jquery  1.4--v1.11  v1.12  v2.0  3.0 的新特性 1.1. Jquery1.12  jQuery 2.2 和 1.12 新版本发布 - OPEN资讯.h ...

  7. [转]C# 6.0 的新特性

    本文的内容包括引入C#6.0中的新的语言特性有哪些. 还有已经被引入的代码名称为 “Roslyn”新编译器. 编译器是开放源码的,并且可以从 codeplex 网站的这个地址下载到源代码: https ...

  8. [PHP] 从PHP 5.6.x 移植到 PHP 7.0.x新特性

    从PHP 5.6.x 移植到 PHP 7.0.x 新特性: 1.标量类型声明 字符串(string), 整数 (int), 浮点数 (float), 布尔值 (bool),callable,array ...

  9. servlet3.0 的新特性之二注解代替了web.xml配置文件

    servlet3.0 的新特性: 注解代替了 web.xml 文件 支持了对异步的处理 对上传文件的支持 1.注解代替了配置文件 1.删除了web.xml 文件 2. 在Servlet类上添加@Web ...

随机推荐

  1. 2019-11-24:postgresql数据库安装,最后报错failed to load SQLModule 问题的解决方案

    安装环境:Windows 10 问题描述:Failed to load sql modules into the database cluster 原因在于 Postgresql 没有安装完全. 解决 ...

  2. 用Helm3构建多层微服务

    Helm是一款非常流行的k8s包管理工具.以前就一直想用它,但看到它产生的文件比k8s要复杂许多,就一直犹豫,不知道它的好处能不能抵消掉它的复杂度.但如果不用,而是用Kubectl来进行调式真的很麻烦 ...

  3. 高德JS依赖分析工程及关键原理

    一.背景 高德 App 进行 Bundle 化后,由于业务的复杂性,Bundle 的数量非常多.而这带来了一个新的问题——Bundle 之间的依赖关系错综复杂,需要进行管控,使 Bundle 之间的依 ...

  4. C#笔记01——注释、进制、基本数据类型、量和输入输出函数

    一.注释 1.单行注释 使用方法:行首加 ” //“: VS2019中的快捷键(以后如果不特加说明都是VS2019): 注释(CTRL+E,C): 取消注释(CTRL+E,U): 2.多行注释 使用方 ...

  5. Linux中shell基础、重定向、管道符、环境变量

    1.什么是shell Shell是系统的用户界面,提供了用户与内核进行交互操作的一种接口(命令解释器).它接收用户输入的命令并把它送入内核去执行.起着协调用户与系统的一致性和在用户与系统之间进行交互的 ...

  6. 浅谈Python中函数式编程、面向对象编程以及古怪的PythonIC

    1.函数式编程作为结构化编程的一种,正在受到越来越多的重视.那么什么事函数式编程呢? 在维基百科中给出了详细的定义,函数式编程又称泛函数编程,是一种编程规范,它将函数运算视为数学上的函数计算.简单的来 ...

  7. day20191120笔记

    1.spring的优势 U盘拷.总结.微信公众号:.2.笔试,课前默写,默完之后要回答问题.3.微服务,带着,知识点,卷子.ssm整个东西讲一下.面试是综合能力.背面试题. 通过基础很重要.学精烂熟于 ...

  8. 堆的python实现及其应用

    堆的概念 优先队列(priority queue)是一种特殊的队列,取出元素的顺序是按照元素的优先权(关键字)大小,而不是进入队列的顺序,堆就是一种优先队列的实现.堆一般是由数组实现的,逻辑上堆可以被 ...

  9. 前端工具-定制ESLint 插件以及了解ESLint的运行原理

    这篇文章目的是介绍如何创建一个ESLint插件和创建一个ESLint rule,用以帮助我们更深入的理解ESLint的运行原理,并且在有必要时可以根据需求创建出一个完美满足自己需求的Lint规则. 插 ...

  10. 使用Jq实现弹出层

    对于前端程序员来说,弹出层是经常用到的,下面我叫大家如何用实现JQuery实现弹出层的效果,代码如下: CSS:弹出层的效果 .mask { position: absolute; top: 0px; ...