当前位置: 首页 > news >正文

【橙子老哥】c# 探究属性与字段本质

hello,大家好,叕到了橙子老哥的分享时间,希望大家一起学习,一起进步。

首先祝大家国庆快乐~

其次,欢迎加入.net意社区,第一时间了解我们的动态,地址:ccnetcore.com

今天,我们来个简单的,来点关于属性与字段有趣的骚操作,废话少说,我们直接开始

1、本质

属性是什么,字段是什么,这里不在这篇文章赘述了,我来直接探究下它的原理

上代码,不解释
我们写一个类,其中包含一个私有属性,一个公开属性

class MyClass
{private string UserName { get; set;}public string Name { get; set; }public void Log(){Console.WriteLine(UserName);}
}

想要知道它到底做了什么,IL一看究竟

[NullableContext(1)]
[Nullable(0)]
internal class MyClass
{[CompilerGenerated][DebuggerBrowsable(DebuggerBrowsableState.Never)]private string <UserName>k__BackingField;[CompilerGenerated][DebuggerBrowsable(DebuggerBrowsableState.Never)]private string <Name>k__BackingField;private string UserName{[CompilerGenerated] get{return this.<UserName>k__BackingField;}[CompilerGenerated] set{this.<UserName>k__BackingField = value;}}public string Name{[CompilerGenerated] get{return this.<Name>k__BackingField;}[CompilerGenerated] set{this.<Name>k__BackingField = value;}}public void Log(){Console.WriteLine(this.UserName);}public MyClass(){base..ctor();}
}

可以看到无论属性是公开还是私有,都会新增一个字段

private string <UserName>k__BackingField;
private string <Name>k__BackingField;
而对应的set、get方法,就有私有及公开区分

  private string UserName{get{return this.<UserName>k__BackingField;}set{this.<UserName>k__BackingField = value;}}public string Name{get{return this.<Name>k__BackingField;}set{this.<Name>k__BackingField = value;}}

这里的get、set,本质上就是一个方法的语法糖,会编译成对应的get方法和set方法,如果熟悉java的人,对这个印象肯定深刻

看到这里,其实答案也就写在脸上了,c# 中的属性,本质上是使用get、set方法,包了一层私有字段。私有字段会叫一个特殊名字<xxxx>k__BackingField,低级别的c#语法是允许命名加特殊字符的,就是防止重名,因为你不能取这样的名称

2、进阶

既然清楚了属性和字段的本质,我们再来玩一下它的一些骚操作

我们可以给私有属性赋值吗?当然可以

对象的操作,C#没有什么是做不到的

例如上方代码中,我们定义的私有的UserName属性,我们实操一下,把这个私有属性赋值

var my=new MyClass(){Name = "张三"};
var property =typeof(MyClass).GetProperty("UserName",BindingFlags.NonPublic | BindingFlags.Instance);
property.SetValue(my,"私有属性");
my.Log();最终输出:私有属性,赋值成功

这个操作也很简单,需要注意的是,在条件中,需要指明BindingFlags.NonPublic | BindingFlags.Instance,否则也是查不出来的,因为默认的方法有一层过滤:

    public PropertyInfo? GetProperty(string name){return this.GetProperty(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);}

另外,属性本质是给一个私有字段包一层,那我们理论上不是可以直接操作字段?当然可以

针对我们上面研究的本质,属性生成的字段叫做:<xxx>k__BackingField,那我们就去找这个字段,并给它赋值

var my=new MyClass(){Name = "张三"};
var property =typeof(MyClass).GetProperty("UserName",BindingFlags.NonPublic | BindingFlags.Instance);var field =typeof(MyClass).GetField("<UserName>k__BackingField",BindingFlags.NonPublic | BindingFlags.Instance);property.SetValue(my,"私有属性");
my.Log();
field.SetValue(my,"私有字段");
my.Log();输出:私有属性 私有字段 属性和字段都修改成功

Nice,是不是很有意思?属性和字段还不直接拿捏


http://www.mrgr.cn/news/41298.html

相关文章:

  • 3271.哈希分割子串
  • Swift并发笔记
  • 【MySQL 06】表的增删查改
  • Mybatis-Flex使用
  • IP 协议的相关特性
  • 【信息系统项目管理师考题预测】范围管理
  • 土地规划与区域经济发展:筑基均衡未来的战略经纬
  • 利士策分享,行走•悟世•惜福: 旅行真谛
  • 告别 backtrader!换这个库实施量化回测
  • sed引入变量中的坑
  • marker=‘o‘, linestyle=‘-‘, color=‘b‘ plt.plot画图参数含义
  • ECharts图表图例4
  • image离散小波变换及pytorch_wavelets实现
  • A股暴涨,不更新文章了
  • 浙江大学《2022年+2023年845自动控制原理真题》 (完整版)
  • Kubernetes环境搭建
  • C#中的static关键字:静态成员与单例模式的实现
  • 在Linux系统安装Nginx
  • Java与C++差异解析
  • 【Linux】进程间关系与守护进程