hello,大家好,叕到了橙子老哥的分享时间,希望大家一起学习,一起进步。
首先祝大家国庆快乐~
其次,欢迎加入.net意社区,第一时间了解我们的动态,地址:ccnetcore.com
今天,我们来个 简单的,来点关于属性与字段有趣的骚操作,废话少说,我们直接开始
1、本质
属性是什么,字段是什么,这里不在这篇文章赘述了,我来直接探究下它的原理
上代码,不解释 我们写一个类,其中包含一个私有属性,一个公开属性
classMyClass
{
privatestringUserName{ get; set;}
publicstringName{ get; set;}
publicvoidLog
{
Console.WriteLine(UserName);
}
}
想要知道它到底做了什么,IL一看究竟
[ NullableContext(1)]
[ Nullable(0)]
internalclassMyClass
{
[ CompilerGenerated]
[ DebuggerBrowsable(DebuggerBrowsableState.Never)]
privatestring<UserName>k__BackingField;
[ CompilerGenerated]
[ DebuggerBrowsable(DebuggerBrowsableState.Never)]
privatestring<Name>k__BackingField;
privatestringUserName
{
[ CompilerGenerated] get
{
returnthis.<UserName>k__BackingField;
}
[ CompilerGenerated] set
{
this.<UserName>k__BackingField = value;
}
}
publicstringName
{
[ CompilerGenerated] get
{
returnthis.<Name>k__BackingField;
}
[ CompilerGenerated] set
{
this.<Name>k__BackingField = value;
}
}
publicvoidLog
{
Console.WriteLine( this.UserName);
}
publicMyClass
{
base..ctor;
}
}
可以看到无论属性是公开还是私有,都会新增一个字段
private string <UserName>k__BackingField; private string <Name>k__BackingField; 而对应的set、get方法,就有私有及公开区分
privatestringUserName
{
get
{
returnthis.<UserName>k__BackingField;
}
set
{
this.<UserName>k__BackingField = value;
}
}
publicstringName
{
get
{
returnthis.<Name>k__BackingField;
}
set
{
this.<Name>k__BackingField = value;
}
}
这里的get、set,本质上就是一个方法的语法糖,会编译成对应的get方法和set方法,如果熟悉java的人,对这个印象肯定深刻
看到这里,其实答案也就写在脸上了,c# 中的属性,本质上是使用get、set方法,包了一层私有字段。私有字段会叫一个特殊名字<xxxx>k__BackingField,低级别的c#语法是允许命名加特殊字符的,就是防止重名,因为你不能取这样的名称
2、进阶
既然清楚了属性和字段的本质,我们再来玩一下它的一些骚操作
我们可以给私有属性赋值吗?当然可以
对象的操作,C#没有什么是做不到的
例如上方代码中,我们定义的私有的UserName属性,我们实操一下,把这个私有属性赋值
varmy= newMyClass{Name = "张三"};
varproperty = typeof(MyClass).GetProperty( "UserName",BindingFlags.NonPublic | BindingFlags.Instance);
property.SetValue(my, "私有属性");
my.Log;
最终输出:私有属性,赋值成功
这个操作也很简单,需要注意的是,在条件中,需要指明BindingFlags.NonPublic | BindingFlags.Instance,否则也是查不出来的,因为默认的方法有一层过滤:
publicPropertyInfo? GetProperty( stringname)
{
returnthis.GetProperty(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
}
另外,属性本质是给一个私有字段包一层,那我们理论上不是可以直接操作字段?当然可以
针对我们上面研究的本质,属性生成的字段叫做:<xxx>k__BackingField,那我们就去找这个字段,并给它赋值
varmy= newMyClass{Name= "张三"};
varproperty= typeof(MyClass).GetProperty( "UserName",BindingFlags.NonPublic|BindingFlags.Instance);
varfield = typeof(MyClass).GetField( "<UserName>k__BackingField",BindingFlags.NonPublic|BindingFlags.Instance);
property.SetValue(my, "私有属性");
my.Log;
field.SetValue(my, "私有字段");
my.Log;
输出:私有属性私有字段 属性和字段都修改成功
Nice,是不是很有意思?属性和字段还不直接拿捏返回搜狐,查看更多
责任编辑: