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占地方了,给读者在阅读代码上造成很大的困难,于是想到能不能把他们“浓缩”成一行,脑子里第一个闪现出的…

添加Chrome插件(Github上下载的压缩文件)

首先把压缩包解压到某个文件夹 然后按照以下步骤进行即可: 点击Chrome浏览器上的设置->扩展程序->开发者模式->点击加载已解压的压缩文件->选中解压过的文件夹确定即可。转载于:https://www.cnblogs.com/yijianzhongqing/p/6277838.html

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…

java二级程序题两个角度_两个角度图_【SCME大一】使用JAVA语言深入理解程序逻辑答案_学小易找答案...

【填空题】《蝶恋花 伫倚危楼风细细 》的作者( )。【简答题】简要概述问卷调查的整体设计?【填空题】父母在,( ),游必有方。【填空题】白居易与刘禹锡并称“( )”。【填空题】白居易,字( )。【填空题】白居易,是唐代伟大的( )主义诗人。【单选题】《红楼梦》最成功处在于塑造了…

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列:接受的客户端连…

elif是不是java关键字_C# 中的#if、#elif、#else、#endif等条件编译符号 (转载)

这些是C#中的条件编译符号。这些指令我在项目中遇到过,查过网络,问过人(当然,既不认识大牛,也不认识小牛,所以没什么收获)。今天翻看一本资料,有提到这个方面的东西,所以写下来和能看到这篇文章…

从零开始React项目架构(四)

前言 使用当前的webpack配置能不能打包构建项目呢?当然可以,但这不是我们想要的,所以,让我们来看一看生产环境需要怎么配置webpack吧 开发 生产环境配置 在根目录创建webpack.pro.config.jsconst path require(path) const webpa…

在OpenCloudOS 上安装.NET 6

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

Linux 命令详解(二)awk 命令

AWK是一种处理文本文件的语言,是一个强大的文本分析工具。之所以叫AWK是因为其取了三位创始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的Family Name的首字符。 语法: awk [选项参数] script varvalue file(s) 或 awk [选项参数] …

linux下vtune使用

安装:http://www.cnblogs.com/jiu0821/p/5943533.html 终端输入amplxe-gui,打开vtune界面。 点击new project,进入project properties界面。进行配置: target:target type选择launch application,application选择程序可…

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

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

数据库 创建 / 查看/ 删除

创建数据库 语法:CREATE DATABASE [IF NOT EXISTS] db_name; 重复创建会报错,所以可以加上if not exists 注意:SQL语句必须以分号结尾 查看有哪些数据库:SHOW DATABASES; 删除数据库 语法:DROP DATABASE [IF EXISTS] dbname;如果…

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写法,仍然没有反应。 排查了后,发现获取的对象错误。手机端上,滚动到顶部&#…