博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
艾伟:C#3.0之自动属性和对象初始化器
阅读量:5775 次
发布时间:2019-06-18

本文共 6085 字,大约阅读时间需要 20 分钟。

  C#3.0中定义属性更加方便,不用再在像之前的版本那样的繁琐,需要先定义存储数据的字段,然后再定义属性器,现在只需要定义属性器就可以了,其它的有编译器自动为我们完成,就可以省去定义字段时需要的那些时间;在对象初始化的时候我们可在对象构造的时候实现对象属性的初始化工作,和集合初始化类似。

  1.匿名属性

  定义属性如下:

public class Employee     {
public int Id { get; set; } public string Name { get; set; } public string Sex { get; set; } public int Age { get; set; } public string BirthDate { get; set; } }

  在C#3.0 之前的写法如下:

public class Employee     {
private int _id; private string _name; private string _sex; private int _age; private string _birthDate; public int Id {
get { return _id; } set { _id = value; } } public string Name {
get { return _name; } set { _name = value; } } public string Sex {
get { return _sex; } set { _sex = value; } } public int Age {
get { return _age; } set { _age = value; } } public string BirthDate {
get { return _birthDate; } set { _birthDate = value; } } }

  仅从代码量上就前者比后者减少了2/3的代码,这对提高效率是显而易见的,那么这些代码都到哪里去了呢?其实那些额外的代码都是由编译器为我们完成的,编译器会将那些我们“省去"的代码编译成托管IL代码的时候补进去,两者中代码在最终生成的IL代码的体积是差不多的。

  上图中的IL代码中我们看到了 k_BackingField之类的字段就是编译器自动产生的字段代码。

  2.对象初始化器

  原来的对象初始化都要进行先创建构造方法,然后才能进行成员的相关操作,C#3.0 提供了对象成员的直接初始化的能力,和初始化一个集合或者是数组一样来初始化对象。

  相对来看,通过对象初始化器对上面的的Employee类进行进行调用:

Employee employee = new Employee { Id = 1, Name = "蓝之风", Age = 24, BirthDate = " 1984-10-21", Sex = "男" };             Console.WriteLine("编号;{0}", employee.Id);             Console.WriteLine("姓名:{0}", employee.Name);             Console.WriteLine("年龄:{0}", employee.Age);             Console.WriteLine("生日:{0}", employee.BirthDate);             Console.WriteLine("性别:{0}", employee.Sex);             Console.WriteLine("请按任意键继续");              Console.ReadLine();

  这句

Employee employee = new Employee { Id = 1, Name = "蓝之风", Age = 24, BirthDate = "1984-10 -21", Sex = "男" };

  就是对象的初始化,看到代码很简洁,输出的结果如下:

  在C#3.0之前的做法是:

Employee employee = new Employee(); employee.Id = 1; employee.Name = "蓝之风"; employee.Age = 24; employee.BirthDate = "1984-10-21"; employee.Sex = "男";                Console.WriteLine("编号;{0}", employee.Id); Console.WriteLine("姓名:{0}", employee.Name); Console.WriteLine("年龄:{0}", employee.Age); Console.WriteLine("生日:{0}", employee.BirthDate); Console.WriteLine("性别:{0}", employee.Sex); Console.WriteLine("请按任意键继续");  Console.ReadLine();

  或者通过重载构造方法的方式来初始化这些属性,二者的达到的效果是相同的,但是前者使用起来方便了些,代码量减少了许多,这个过程是怎么完成的呢?其实C#本身并没有太大的变化,这些都是在语法上的一些改变,使得编写代码的时候更方便效率更高,把一些编译器可以推断出来完成的工作让编译器来做了,编译器在编译程序的时候将我们没有实现的代码替我们实现来生成IL代码的:

method private hidebysig static void  Main(string[] args) cil managed {
.entrypoint // 代码大小 175 (0xaf) .maxstack 2 .locals init ([0] class CS30.Employee employee, [1] class CS30.Employee '<>g__initLocal0') IL_0000: nop IL_0001: newobj instance void CS30.Employee::.ctor() IL_0006: stloc.1 IL_0007: ldloc.1 IL_0008: ldc.i4.1 IL_0009: callvirt instance void CS30.Employee::set_Id(int32) IL_000e: nop IL_000f: ldloc.1 IL_0010: ldstr bytearray (DD 84 4B 4E CE 98 ) // ..KN.. IL_0015: callvirt instance void CS30.Employee::set_Name(string) IL_001a: nop IL_001b: ldloc.1 IL_001c: ldc.i4.s 24 IL_001e: callvirt instance void CS30.Employee::set_Age(int32) IL_0023: nop IL_0024: ldloc.1 IL_0025: ldstr "1984-10-21" IL_002a: callvirt instance void CS30.Employee::set_BirthDate(string) IL_002f: nop IL_0030: ldloc.1 IL_0031: ldstr bytearray (37 75 ) // 7u IL_0036: callvirt instance void CS30.Employee::set_Sex(string) IL_003b: nop IL_003c: ldloc.1 IL_003d: stloc.0 IL_003e: ldstr bytearray (16 7F F7 53 3B 00 7B 00 30 00 7D 00 ) // S;.{.0.}. IL_0043: ldloc.0 IL_0044: callvirt instance int32 CS30.Employee::get_Id() IL_0049: box [mscorlib]System.Int32 IL_004e: call void [mscorlib]System.Console::WriteLine(string, object) IL_0053: nop IL_0054: ldstr bytearray (D3 59 0D 54 3A 00 7B 00 30 00 7D 00 ) // .Y.T:.{.0.}. IL_0059: ldloc.0 IL_005a: callvirt instance string CS30.Employee::get_Name() IL_005f: call void [mscorlib]System.Console::WriteLine(string, object) IL_0064: nop IL_0065: ldstr bytearray (74 5E 84 9F 3A 00 7B 00 30 00 7D 00 ) // t^..:.{.0.}. IL_006a: ldloc.0 IL_006b: callvirt instance int32 CS30.Employee::get_Age() IL_0070: box [mscorlib]System.Int32 IL_0075: call void [mscorlib]System.Console::WriteLine(string, object) IL_007a: nop IL_007b: ldstr bytearray (1F 75 E5 65 3A 00 7B 00 30 00 7D 00 ) // .u.e:.{.0.}. IL_0080: ldloc.0 IL_0081: callvirt instance string CS30.Employee::get_BirthDate() IL_0086: call void [mscorlib]System.Console::WriteLine(string, object) IL_008b: nop IL_008c: ldstr bytearray (27 60 2B 52 3A 00 7B 00 30 00 7D 00 ) // '`+R:.{.0.}. IL_0091: ldloc.0 IL_0092: callvirt instance string CS30.Employee::get_Sex() IL_0097: call void [mscorlib]System.Console::WriteLine(string, object) IL_009c: nop IL_009d: ldstr bytearray (F7 8B 09 63 FB 4E 0F 61 2E 95 E7 7E ED 7E 2E 00 // c.N.a~.~.. 2E 00 2E 00 ) // . IL_00a2: call void [mscorlib]System.Console::WriteLine(string) IL_00a7: nop IL_00a8: call string [mscorlib]System.Console::ReadLine() IL_00ad: pop IL_00ae: ret } // end of method Program::Main

  从上面的IL代码中可以清晰的看到,首先创建了Employee的实例,然后才对相关的属性进行赋值操作的。

  3.总结:

  自动属性和对象初始化器都是C#3.0提供的语法级别的功能改进,是一种语法糖,是编写代码的效率更高,将一些重复性的工作交给编译器来做,但是这种改变,也增加了代码的不透明性,这点在隐式类型中体现的更为突出,增加了代码理解的难度,这些仅仅是提供给代码编写人员的一种选择,如果不喜欢也可以按照原来的方式来书写自己的代码也未尝不可。

转载于:https://www.cnblogs.com/waw/archive/2011/08/28/2156811.html

你可能感兴趣的文章
消费贷用户70%月收入低于5000元 80、90后是主要人群
查看>>
2018年内蒙古外贸首次突破1000亿元
查看>>
CTOR有助于BCH石墨烯技术更上一层楼
查看>>
被遗忘的CSS
查看>>
Webpack中的sourcemap以及如何在生产和开发环境中合理的设置sourcemap的类型
查看>>
做完小程序项目、老板给我加了6k薪资~
查看>>
java工程师linux命令,这篇文章就够了
查看>>
关于React生命周期的学习
查看>>
webpack雪碧图生成
查看>>
搭建智能合约开发环境Remix IDE及使用
查看>>
Spring Cloud构建微服务架构—服务消费基础
查看>>
RAC实践采坑指北
查看>>
runtime运行时 isa指针 SEL方法选择器 IMP函数指针 Method方法 runtime消息机制 runtime的使用...
查看>>
LeetCode36.有效的数独 JavaScript
查看>>
Scrapy基本用法
查看>>
PAT A1030 动态规划
查看>>
自制一个 elasticsearch-spring-boot-starter
查看>>
软件开发学习的5大技巧,你知道吗?
查看>>
java入门第二季--封装--什么是java中的封装
查看>>
【人物志】美团前端通道主席洪磊:一位产品出身、爱焊电路板的工程师
查看>>