init 访问器只能初始化时赋值,是真的吗?

前言

C# 提供的 init 关键字用于在属性中定义访问器方法,可以让属性仅能在对象初始化的时候被赋值,其他时候只能为只读属性的形式。

例如下面代码可以正常执行:

public class Demo
{public string Name { get; init; }
}var demo = new Demo { Name = "Demo" };

但是当我们想修改属性值时,就会报错:

demo.Name = "My IO";

da7d11203c145b7d45c7f525a9c42eae.png

看来只能初始化时赋值了,真的是这样吗?

原理

首先,我们来看看 init 最后会编译成什么。

反编译代码,发现生成的代码和普通属性完全一致:

public class Demo
{// Token: 0x17000001 RID: 1// (get) Token: 0x06000003 RID: 3 RVA: 0x00002085 File Offset: 0x00000285// (set) Token: 0x06000004 RID: 4 RVA: 0x0000208D File Offset: 0x0000028Dpublic string Name { get; set; }
}

进一步使用 IL DASM 反汇编成中间语言 (IL) 代码:

.property instance string Name(){.get instance string ConsoleApp1.Demo::get_Name().set instance void modreq([System.Runtime]System.Runtime.CompilerServices.IsExternalInit) ConsoleApp1.Demo::set_Name(string)} // end of property Demo::Name

可以看到,属性还是会编译成get_XXXset_XXX方法,只是 set_Name(string) 方法有一个 modreq 修饰符,并使用了 IsExternalInit 类型。

查看官方文档[1],原来使用 modreq 特性是为了让编译器知道它会限制对属性的访问,更为关键的是,它不会在以下情况下受到保护

  • 成员反射

  • 使用 dynamic

  • 不识别 modreqs 的编译器

实现

既然如此,我们可以使用反射在任何时候为 init-only 属性赋值:

var demo = new Demo { Name = "Demo" };typeof(Demo).GetProperty("Name").SetValue(demo, "My IO"); 
Console.WriteLine(demo.Name);//输出
My IO

结论

今天,我们了解到,init 其实是 C# 编译器的功能,在运行时还是可以修改其值的。

参考资料

[1]

官方文档: https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/proposals/csharp-9.0/init

添加微信号【MyIO666】,邀你加入技术交流群

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/283005.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

eclipse实现代码块折叠-类似于VS中的#region……#endregion

背 景 刚才在写代码的时候,写了十几行可以说是重复的代码: 如果整个方法或类中代码多了,感觉它们太TM占地方了,给读者在阅读代码上造成很大的困难,于是想到能不能把他们“浓缩”成一行,脑子里第一个闪现出的…

java定义基础变量语句_java语言基础-变量

一丶变量的基本概念1.什么是变量(1).内存中的一个存储区域(2).该区域有自己的名称(变量名),和类型(数据类型)(3.)该区域的数据可以在同一类型范围内不断变化(定义变量的主要目的是因为数据的不确定性)2.为什么要定义变量用来不断存放同一类型的常量,并可以重复使用3…

C# WPF MVVM模式[经典]案例

01—前言Caliburn.Micro(简称CM)一经推出便备受推崇,作为一款MVVM开发模式的经典框架,越来越多的受到wpf开发者的青睐.我们看一下官方的描述:Caliburn是一个为Xaml平台设计的小型但功能强大的框架。Micro实现了各种UI模式,用于解决…

shell数组

定义数组[rootwy shell]# a(1 2 3 4)显示数组[rootwy shell]# echo ${a[]}1 2 3 4[rootwy shell]# echo ${a[*]}1 2 3 4显示数组中的某个元素[rootwy shell]# echo ${a[0]}1增加元素[rootwy shell]# a[4]9[rootwy shell]# echo ${a[*]}1 2 3 4 9修改元素值 [rootwy shell]# a[2…

LINUX中常用操作命令

LINUX中常用操作命令 引用:http://www.daniubiji.cn/archives/25 Linux简介及Ubuntu安装 常见指令系统管理命令打包压缩相关命令关机/重启机器Linux管道Linux软件包管理vim使用用户及用户组管理文件权限管理Linux简介及Ubuntu安装 Linux,免费开源&#x…

Log4j编写

来自: http://www.blogjava.net/zJun/archive/2006/06/28/55511.html Log4J的配置文件(Configuration File)就是用来设置记录器的级别、存放器和布局的,它可接keyvalue格式的设置或xml格式的设置信息。通过配置,可以创建出Log4J的运行环境。1. 配置文件L…

C# 为什么高手喜欢用StartsWith而不是Substring进行字符串匹配?

字符串的截取匹配操作在开发中非常常见,比如下面这个示例:我要匹配查找出来字符串数组中以“abc”开头的字符串并打印,我下面分别用了两种方式实现,代码如下:using System;namespace ConsoleApp23 {class Program{stat…

Nginx 服务器开启status页面检测服务状态

原文:http://www.cnblogs.com/hanyifeng/p/5830013.html 一、Nginx status monitor 和apache 中服务器状态一样。输出的内容如: 第1列: 当前与http建立的连接数,包括等待的客户端连接:2第2列:接受的客户端连…

在OpenCloudOS 上安装.NET 6

开源操作系统社区 OpenCloudOS 由腾讯与合作伙伴共同倡议发起,是完全中立、全面开放、安全稳定、高性能的操作系统及生态。OpenCloudOS 沉淀了多家厂商在软件和开源生态的优势,继承了腾讯在操作系统和内核层面超过10年的技术积累,在云原生、稳…

java产生的数字发送到页面_JAVA中数字证书的维护及生成方法

Java中的keytool.exe可以用来创建数字证书,所有的数字证书是以一条一条(采用别名区别)的形式存入证书库的中,证书库中的一条证书包含该条证书的私钥,公钥和对应的数字证书的信息。证书库中的一条证书可以导出数字证书文件,数字证书…

IDEA破解 2017 IDEA license server 激活(可用)

进入ide主页面,help-register-license server,然后输入 http://idea.iteblog.com/key.PHP(注意:php要小写)即可~ 转载于:https://www.cnblogs.com/austinspark-jessylu/p/7232982.html

《ASP.NET Core 6框架揭秘》实例演示[20]:“数据保护”框架基于文件的密钥存储...

《数据加解密与哈希》演示了“数据保护”框架如何用来对数据进行加解密,而“数据保护”框架的核心是“密钥管理”。数据保护框架以XML的形式来存储密钥,默认的IKeyManager实现类型为XmlKeyManager。接下来我们通过模拟代码和实例演示的形式来介绍一下Xml…

使用msui的回到顶部的一个小问题

2019独角兽企业重金招聘Python工程师标准>>> 回到顶部,一直没反应。 zepto加了动画后,依然如此。原生写法,jquery写法,仍然没有反应。 排查了后,发现获取的对象错误。手机端上,滚动到顶部&#…

口袋精灵加速版java_口袋妖怪TCG!口袋对决加速版教程(免ROOT)

原标题:口袋妖怪TCG!口袋对决加速版教程(免ROOT)《口袋对决》是一款以口袋精灵对战为核心玩法的集换式卡牌游戏,原汁原味的口袋画风,丰富多彩的各系精灵,策略竞技的属性相克。在5分钟一局的卡牌对战中,你将…

C#发布程序添加其他程序文件

注:程序发布文件,默认只发布自身程序直接引用的相关文件(A程序)。 如果需要添加其他程序(不同的应用程序B)文件,操作方法如下: 第一步:将B程序文件复制到A程序 第二步:将B程序文件右键--》属性做如下更改&a…

k8s 读书笔记 - 初始化容器 Init Container

Init Container 概述Init Container(Init 容器) 是一种特殊容器,在 Pod 内的应用容器启动之前运行,执行相关的初始化操作。Init 容器可以包括一些应用镜像中不存在的 实用工具 和 安装脚本 。每个 Pod 中可以包含一个或多个容器&a…

捕获 BackgroundService 中的异常 | 学学官方是如何实现的

前言上次,我们实现了《使用“装饰者模式”捕获 BackgroundService 中的异常》。结果发现,微软已经发现了这个问题,并在 .NET 6 中解决了。(囧)让我们验证一下:using IHost host Host.CreateDefaultBuilder…

使用badboy录制脚本 结合Jmeter一起测试。

1.badboy介绍 Badboy是一款不错的Web自动化测试工具,如果你将它用于非商业用途,或者用于商业用途安装Badboy 的机器数量不超过5台,你是不需要为它支付任何费用的。Badboy提供了将Web测试脚本直接导出生成JMeter 脚本的功能,并且这…

centOS下安装jdk1.8

2019独角兽企业重金招聘Python工程师标准>>> 本文记录了在vm下安装的centOS7下安装jdk1.8的过程 需要的工具及jdk: jdk-8u171-linux-x64.tar.gz 可以到官网去下 cecureFX 用于文件的传输 过程: 本次centOS7使用VMware Workstation 14 P…

盘点大厂的那些开源项目 - 滴滴出行

滴滴出行是涵盖出租车、 专车、滴滴快车、 顺风车、代驾及大巴、货运等多项业务在内的一站式出行平台。Nightingale 夜莺分类:监控系统夜莺是一套分布式高可用的运维监控系统,最大的特点是混合云支持,既可以支持传统物理机虚拟机的场景&#…