[C#6] 5-自动属性增强

0. 目录

C#6 新增特性目录

1. 老版本代码

 1 internal class Person
 2 {
 3     public string Name { get; private set; }
 4     public int Age { get; private set; }
 5 
 6     public Person(string name,int age)
 7     {
 8         Name = name;
 9         Age = age;
10     }
11 }

通常情况下,C#的属性可以很好的帮助我们完成工作,比如上面的代码。在为属性赋值的时候,我们可以在任意地方为其赋值。但是并没有一种像是字段一样的声明且立即初始化的语法来简化默认值的设定。C#6为我们带来了这种新的语法,像是为字段赋值一样为属性赋值。

我们也知道,C#的属性实际上是一个编译器自动生成的私有字段、get_xxx和set_xxx、一条元数据组成,比如上面的代码编译后:

<Name>k__BackingField字段的IL

1 .field private string '<Name>k__BackingField'
2 .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
3 .custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 )

表示一个私有字段,第2行分别表示这个自动是编译器自动生成的,第3行表示该字段不显示在Debugger窗口中。

get_Name方法的IL:

 1 .method public hidebysig specialname instance string 
 2         get_Name() cil managed
 3 {
 4   .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
 5   // Code size       7 (0x7)
 6   .maxstack  8
 7   IL_0000:  ldarg.0
 8   IL_0001:  ldfld      string csharp6.Person::'<Name>k__BackingField'
 9   IL_0006:  ret
10 } // end of method Person::get_Name

这也是一个自动生成的方法。

set_Name方法的IL:

 1 .method private hidebysig specialname instance void 
 2         set_Name(string 'value') cil managed
 3 {
 4   .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
 5   // Code size       8 (0x8)
 6   .maxstack  8
 7   IL_0000:  ldarg.0
 8   IL_0001:  ldarg.1
 9   IL_0002:  stfld      string csharp6.Person::'<Name>k__BackingField'
10   IL_0007:  ret
11 } // end of method Person::set_Name

同样是一个自动生成的方法。

Name属性的IL:

1 .property instance string Name()
2 {
3   .get instance string csharp6.Person::get_Name()
4   .set instance void csharp6.Person::set_Name(string)
5 } // end of property Person::Name

表示Name属性由一个get方法和set方法组成。

2. 自动属性增强语法

 1 internal class Person
 2 {
 3     //声明读写属性、且初始化默认值
 4     public string Name { get; set; } = "blackheart";
 5 
 6     //声明只读属性、且初始化默认值
 7     public int Age { get; } = 1;
 8 
 9     //声明只读属性
10     public string Note { get; }
11 
12     public Person(string note)
13     {
14         //在构造器中为只读属性初始化默认值
15         Note = note;
16     }
17 
18     private void func1()
19     {
20         //error,只能在构造器中初始化
21         //Note = "123";
22         //Age = 1;
23         //可以修改,因为有set访问器
24         Name = "new name";
25     }
26 }

这种新语法会在没有set访问器的时候把隐藏的私有字段设置为只读字段(readonly ),只允许在声明的时候设置初始值或者在构造器里面赋值。看看IL:

只有Name属性具有set_Name方法,而Age和Note属性则没有set访问器,且对应的私有字段被设置为"initonly",表示这是一个只读字段。

构造器方法,Name{get;set;}="blackheart"和Age{get;}=1的初始化操作部分被转移到实例构造函数".ctor"方法中。

 1 .method public hidebysig specialname rtspecialname 
 2         instance void  .ctor(string note) cil managed
 3 {
 4   // Code size       34 (0x22)
 5   .maxstack  8
 6   IL_0000:  ldarg.0
 7   IL_0001:  ldstr      "blackheart"
 8   IL_0006:  stfld      string csharp6.Person::'<Name>k__BackingField'
 9   IL_000b:  ldarg.0
10   IL_000c:  ldc.i4.1
11   IL_000d:  stfld      int32 csharp6.Person::'<Age>k__BackingField'
12   IL_0012:  ldarg.0
13   IL_0013:  call       instance void [mscorlib]System.Object::.ctor()
14   IL_0018:  nop
15   IL_0019:  nop
16   IL_001a:  ldarg.0
17   IL_001b:  ldarg.1
18   IL_001c:  stfld      string csharp6.Person::'<Note>k__BackingField'
19   IL_0021:  ret
20 } // end of method Person::.ctor

和之前的语法生成的代码可以说是一致的,均是生成为一个字段、get_xxx和set_xxx方法和对应的属性元数据,本质依然是编译器的语法简化。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏思考的代码世界

Python基础学习01天

2180
来自专栏IT可乐

深入理解计算机系统(3.8)------数组分配和访问

  上一篇博客我们讲解了汇编语言中过程(函数)的调用实现。理解数据如何在调用者和被调用者之间传递,以及在被调用者当中局部变量内存的分配以及释放是最重要的。那么这...

22010
来自专栏淡定的博客

python入门基础语法总结

1073
来自专栏大前端_Web

js浮点数加减乘除

版权声明:本文为吴孔云博客原创文章,转载请注明出处并带上链接,谢谢。 https://blog.csdn.net/wkyseo/articl...

1633
来自专栏大闲人柴毛毛

稳扎稳打JavaScript(一)——作用域链内存模型

几个概念 在开始之前,先了解几个概念。 1.1. 作用域 作用域是指当前正在执行的代码能够访问到变量的范围; 每个函数都有各自的作用域,存储函数所有的局部变量...

4798
来自专栏九彩拼盘的叨叨叨

JavaScript 字符串练习题

如果对字符串的 API 不是很熟悉,可查阅 W3School JavaScript String API。

891
来自专栏python3

python字符串

1.    S.find(substr,[start,[end]])    返回S中出现substr的第一个字母的标号,如果S中没有substr则返回-1,st...

992
来自专栏Python小屋

数学老师从没这么教过,乘法竖式中进位可以是多位(附Python实现与测试源码)

大概十五年前,曾经写过一个C语言版本的类似代码。核心思想是:在乘法竖式计算过程中,每次的进位实际上是可以超过一位的,虽然老师从来没有这么教过。 ? 这样的操作在...

3416
来自专栏蜕变

Python 数据类型

Python主要数据类型包括list(列表)、tuple(元组)、dict(字典)和set(集合)等对象,下面逐一介绍这些Python数据类型。

850
来自专栏日常分享

Spring 学习笔记(七)—— 切入点表达式

  语法结构:   execution(   方法修饰符  方法返回值  方法所属类 匹配方法名 (  方法中的形参表 )  方法申明抛出的异常  )

601

扫码关注云+社区

领取腾讯云代金券