C#中字段、属性、只读、构造函数赋值、反射赋值的相关

C#中字段、属性和构造函数赋值的问题


提出问题

首先提出几个问题:

1、如何实现自己的注入框架?

2、字段和自动属性的区别是什么?

3、字段和自动属性声明时的直接赋值和构造函数赋值有什么区别?

4、为什么只读字段和只读自动属性(只有get没有set访问器)都可以在构造函数中进行赋值?

5、反射可以给只读字段或者只读属性进行赋值吗?

6、自动属性和普通属性的区别?

这些问题是我在试着写自己的注入实现时遇到的问题。这些问题应该在学习C#时的第一节课就应该学到了,我看网上还有人分享说他在面试时遇到面试官问为什么只读字段和只读自动属性可以在构造函数中进行赋值,他没有回答上来,然后他写文章探讨这个问题,却没有得出一个明显的答案,实在可惜。网上关于只读属性有些是写ReadOnly特性的,读到这些文章直接跳过吧,老版本的C#现在看也没什么帮助。


给出答案

2、属性比字段多了get/set访问器;字段是在内存中声明的一个内存空间,可以实实在在的存储值;属性像字段一样使用,却可以有自己的代码段,能赋值取值,是因为访问属性就是调用属性的get/set方法对字段进行取值赋值(或者不操作字段);在MSDN上,建议字段作为类的私有变量使用private/protected修饰,属性则往往作为共有属性使用public修饰;字段的读取和操作都是直接操作内存,属性是调用get/set访问器,所以字段比属性快

3、准确来说,没有区别。区别仅仅是直接赋值先执行,构造函数赋值后执行。在生成的IL中间语言(C#代码先编译成IL代码,然后才编译成汇编语言)中,字段直接赋值和构造函数赋值是在同一个代码段中(构造函数中)的。

4、这个问题可以和上面的问题联合起来回答。构造函数作为实例化一个类的入口,是最先访问的。字段的直接赋值其实也是放在构造函数中执行的,所以才说直接赋值和构造函数赋值没有区别。“只读”的限制只是由C#编译器(CLR)维护的,我觉得全名应该叫做“除构造函数外只读”更加准确,这是C#语法的规则记住就行(这是当然,直接赋值其实是放在构造函数中进行赋值的,如果构造函数不能赋值那只读字段没有值和没有声明一样);

5、这个问题又可以和上面的问题联系起来一起回答。通过反射可以给自读字段赋值但是无法给只读属性进行赋值(不相信的可以试一下)。对只读字段的赋值是因为绕过了C#编译器(CLR)的只读显示,对只读属性赋值的话是还是调用set访问器对字段进行赋值,因为没有set访问器所以允许后会报错。那么问题来了,那为什么只读自动属性没有set访问器还可以在构造函数中赋值呢?其实只读自动属性在构造函数中进行赋值,实质上是对字段进行赋值,和属性的get/set访问器没有关系。

6、区别是什么?上面一直强调自动属性,是因为自动属性和普通属性不一样,比如只读普通属性(没有set访问器)无法在构造函数中赋值。在没有自动属性之前,普通属性使用步骤是首先声明一个字段如_id,然后声明一个属性Id,在get和set访问器中做一些操作,这些操作大多数是对字段_id的操作,但是有时候和字段没有关系。普通属性可以像字段一样通过“.”的方式调用,但又像方法一样具有代码段(普通属性从来不开辟内存空间)。

但是C#3.0之后引入了自动属性,声明方式如public int id { get; set; },C#6.0之后又有了public string FirstName { get; set; } = "Jane"。自动属性肯定开辟了内存空间然后才有了自动属性的直接赋值。其实在类中声明自动属性会在编译成IL中间语言中声明一个隐藏字段,然后生成隐藏字段的get/set方法,然后生成get/set访问器。这里可以解释为什么只读普通属性无法在构造函数中赋值(和直接赋值)而只读自动属性可以在构造函数中赋值(和直接赋值),因为不论直接赋值还是在构造函数中赋值,生成的IL代码中的构造函数中,操作的都是隐藏字段,并没有访问属性的set访问器。(注意这里只是说的类中的自动属性,接口中也是可以有自动属性的,但是接口的自动属性并不会生成隐藏字段只是定义get/set访问器)


开始解释

通过C#生成的IL中间语言代码可以知道的更清楚

640?wx_fmt=png

640?wx_fmt=png640?wx_fmt=png

可以看到,自动属性会生成一个名称为 '<age>k__BackingField' 的隐藏私有字段+私有字段的get/set方法+属性代码段;

可以看到IL代码生成了User的构造函数 .ctor,ctor是构造函数(Constructor)。

不论直接赋值还是构造函数赋值,都是在.ctor中执行的,并且操作的都是字段,自动属性的赋值操作的是隐藏字段

  public interface IUser{    int id { get; set; }}

640?wx_fmt=png

可以看到,接口中的自动属性并没有生成隐藏字段

其他说明

1、上文中提到“反射可以给只读字段进行赋值但是无法给只读属性进行赋值”。无法给只读属性进行赋值是因为没有set访问器。但是我们已经知道了可以给字段赋值,并且只读属性会生成隐藏字段,那我们是不是可以通过给隐藏字段进行赋值间接达到给自动属性赋值的目的呢?答案是可以的!

定义User的只读自动属性

640?wx_fmt=png

控制台的反射赋值代码:

640?wx_fmt=png

运行

640?wx_fmt=png

2、因为隐藏字段是私有的,所以取到隐藏字段需要  BindingFlags.NonPublic

3、只读自动属性说明不想被访问到那为什么还要给它赋值呢?这个问题……做着玩,项目中我觉得也没有什么用到的机会……

原文地址:https://www.cnblogs.com/gdpw/p/9463145.html


.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com

640?wx_fmt=jpeg


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

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

相关文章

点分治学习笔记

点分治学习笔记 模板题[洛谷P3806] 题意&#xff1a;给定一棵有n个点的树&#xff0c;询问树上距离为k的点对是否存在。 做法&#xff1a;对于一个点\(u\)&#xff0c;树上所有的路径可以分为两类&#xff0c;一类是经过点\(u\)&#xff0c;另一类是没有经过点\(u\)&#xff0c…

【暴力】心中报情(jzoj 2317)

心中报情 jzoj 2317 题目大意&#xff1a; 在一个n*m矩阵中&#xff0c;有k个选定的子矩阵&#xff0c;每个矩阵有一个代价&#xff0c;现在让你选两个子矩阵&#xff08;有相交的&#xff09;&#xff0c;使他们覆盖的元素之和减去他两的代价最大&#xff08;重复的只算一次…

BZOJ1251 序列终结者

BZOJ1251 序列终结者 题目&#xff1a;1. 将\([L,R]\)这个区间内的所有数加上\(V\)。 2. 将\([L,R]\)这个区间翻转。 3. 求\([L,R]\)这个区间中的最大值。 最开始所有元素都是\(0\)。 存个模板 Code #include <cstdio> #include <algorithm> #include <cstring&…

jzoj5698-[gdoi2018day1]密码锁【贪心,差分】

正题 题目大意 nnn个数字&#xff0c;每次可以让一个区间加或减111。然后数字是一个[0,m−1][0,m-1][0,m−1]的循环&#xff0c;求最少次数让所有数字变成000 解题思路 我们做一个%m\%m%m意义下的差分数组之后问题就变成了选择两个位置一增一减使得所有的变成000。 那么我们可…

.NET Core开发日志——RequestDelegate

本文主要是对.NET Core开发日志——Middleware的补遗&#xff0c;但是会从看起来平平无奇的RequestDelegate开始叙述&#xff0c;所以以其作为标题&#xff0c;也是合情合理。RequestDelegate是一种委托类型&#xff0c;其全貌为public delegate Task RequestDelegate(HttpCont…

[SDOI2008]仪仗队

牛客网 题目描述 作为体育委员&#xff0c;C君负责这次运动会仪仗队的训练。 仪仗队是由学生组成的N * N的方阵&#xff0c;为了保证队伍在行进中整齐划一&#xff0c;C君会跟在仪仗队的左后方&#xff0c;根据其视线所及的学生人数来判断队伍是否整齐(如下图)。 现在&#xff…

【贪心】失意(jzoj 2318)

失意 jzoj 2318 题目大意&#xff1a; 在x轴上给出n条线段&#xff0c;让你选m条线段&#xff0c;使他们的相交部分尽量大 输入样例&#xff1a; 4 6 3 3 8 4 12 2 6 1 10 5 9 11 12输出样例&#xff1a; 4 1 2 4解题思路&#xff1a; 我们先从左到右选m条线段&#xff…

Link Cut Tree 学习笔记

Link Cut Tree 学习笔记 说在前边 最近补 CF 碰见一道 LCT &#xff0c;就打算学习一下这个东西。。。顺便复习一下 splay。 具体算法及实现 参考了FlashHu&#xff0c; Candy? P3690 【模板】Link Cut Tree &#xff08;动态树&#xff09; 题目&#xff1a;给定n个点以及每个…

.NetCore SkyWalking APM实现服务器监控环境安装及基础使用

下载Java 8 SDK wget --no-cookies --no-check-certificate --header "Cookie: gpw_e24http%3A%2F%2Fwww.oracle.com%2F; oraclelicenseaccept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jdk/8u171-b11/512cd62ec5174c3487ac17c61aaa89e8/jdk…

P1129-[ZJOI2007]矩阵游戏【最大匹配】

正题 题目链接:https://www.luogu.com.cn/problem/P1129 题目大意 n∗mn*mn∗m的网格上有0/10/10/1&#xff0c;可以选择交换两行或两列&#xff0c;求能否让对角线上全是111。 解题思路 因为可以交换&#xff0c;所以是每一行都要和每一列配对。而第iii行能够和第jjj列配对的…

身体训练

牛客网 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 32768K&#xff0c;其他语言65536K 64bit IO Format: %lld 题目描述 美团外卖的配送员用变速跑的方式进行身体训练。 他们训练的方式是&#xff1a;n个人排成一列跑步&#xff0c;前后两人…

ASP.NET Core依赖注入最佳实践,提示技巧

分享翻译一篇Abp框架作者(Halil İbrahim Kalkan)关于ASP.NET Core依赖注入的博文.在本文中,我将分享我在ASP.NET Core应用程序中使用依赖注入的经验和建议.这些原则背后的目的是:有效地设计服务及其依赖关系防止多线程问题防止内存泄漏防止潜在的错误本文假设你已经熟悉基本的…

【匈牙利算法】指引(jzoj 2319)

指引 jzoj 2319 题目大意&#xff1a; 在平面上有n个人和出口&#xff0c;一个出口只能让一个人进&#xff0c;每个人只能向右向上走&#xff0c;问最多让多少个人到出口 输入样例&#xff1a; 6 3 2 0 3 1 1 3 4 2 0 4 5 5输出样例&#xff1a; 2解题思路&#xff1a; …

Codeforces1142D

Codeforces1142D 做法&#xff1a;构建一个可以识别出合法串的自动机&#xff0c;然后就可以想办法在上边 dp 出答案。 首先&#xff0c;按照最直观的思路画一画这个自动机&#xff0c;找到每一个状态s如何推出它的后继t&#xff0c;然后通过状态的转移方式&#xff0c;找到等价…

P3620-[APIO/CTSC2007]数据备份【贪心,堆,链表】

正题 题目链接:https://www.luogu.com.cn/problem/P3620 题目大意 一条线上有nnn个位置&#xff0c;选出kkk对使得它们的距离差之和最小。 解题思路 因为一定是连接相邻的最优&#xff0c;那么可以在差分数组上做&#xff0c;相当于我们在一个差分数组上选择一些不相邻的数使…

Maximize The Beautiful Value

传送 时间限制&#xff1a;C/C 2秒&#xff0c;其他语言4秒 空间限制&#xff1a;C/C 131072K&#xff0c;其他语言262144K 64bit IO Format:%lld 题目描述 Today HH finds a non-decreasing sequence(a1,a2…an,ai≤ai1), he thinks it’s not beautiful so he wants to make …

纪中C组模拟赛总结(2019.9.7)

成绩&#xff1a; 注&#xff1a;rankrankrank是有算其他dalaodalaodalao的 hky,wjj,lthhky,wjj,lthhky,wjj,lth三位dalaodalaodalao竟不屑于交题 rankrankranknamenamenamescorescorescoreT1T1T1T2T2T2T3T3T3T4T4T4888lyflyflyf110110110101010000100100100000242424fyfyfy45…

MEF 插件式开发 - DotNetCore 初体验

背景叙述在传统的基于 .Net Framework 框架下进行的 MEF 开发&#xff0c;大多是使用 MEF 1&#xff0c;对应的命名空间是 System.ComponentModel.Composition。在 DotNet Core 中&#xff0c;微软为了伟大的跨平台策略&#xff0c;引入了 MEF 2&#xff0c;其对应的命名空间是…

反向传播算法学习笔记

反向传播算法(Back propagation) 目的及思想 我们现在有一堆输入&#xff0c;我们希望能有一个网络&#xff0c;使得通过这个网络的构成的映射关系满足我们的期待。也就是说&#xff0c;我们在解决这个问题之前先假设&#xff0c;这种映射可以用网络的模型来比较好的描述。为什…

AT1219-歴史の研究(历史研究)【回滚莫队】

正题 题目链接:https://www.luogu.com.cn/problem/AT1219 题目大意 nnn个数字&#xff0c;mmm次询问一个区间内ti∗it_i*iti​∗i的最大值&#xff0c;tit_iti​即区间内iii的出现次数。 解题思路 用回滚莫队的思想&#xff0c;对于在不同块中的询问&#xff0c;我们把左端点…