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.pswp.cn/news/283005.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/283005.shtml
英文地址,請注明出處:http://en.pswp.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寫法,仍然沒有反應。 排查了后,發現獲取的對象錯誤。手機端上,滾動到頂部&#…