艾伟:C#3.0之自动属性和对象初始化器

  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:  nopIL_0001:  newobj     instance void CS30.Employee::.ctor()IL_0006:  stloc.1IL_0007:  ldloc.1IL_0008:  ldc.i4.1IL_0009:  callvirt   instance void CS30.Employee::set_Id(int32)IL_000e:  nopIL_000f:  ldloc.1IL_0010:  ldstr      bytearray (DD 84 4B 4E CE 98 )                               // ..KN..IL_0015:  callvirt   instance void CS30.Employee::set_Name(string)IL_001a:  nopIL_001b:  ldloc.1IL_001c:  ldc.i4.s   24IL_001e:  callvirt   instance void CS30.Employee::set_Age(int32)IL_0023:  nopIL_0024:  ldloc.1IL_0025:  ldstr      "1984-10-21"IL_002a:  callvirt   instance void CS30.Employee::set_BirthDate(string)IL_002f:  nopIL_0030:  ldloc.1IL_0031:  ldstr      bytearray (37 75 )                                           // 7uIL_0036:  callvirt   instance void CS30.Employee::set_Sex(string)IL_003b:  nopIL_003c:  ldloc.1IL_003d:  stloc.0IL_003e:  ldstr      bytearray (16 7F F7 53 3B 00 7B 00 30 00 7D 00 )             // S;.{.0.}.  IL_0043:  ldloc.0IL_0044:  callvirt   instance int32 CS30.Employee::get_Id()IL_0049:  box        [mscorlib]System.Int32IL_004e:  call       void [mscorlib]System.Console::WriteLine(string,                                                                object)IL_0053:  nopIL_0054:  ldstr      bytearray (D3 59 0D 54 3A 00 7B 00 30 00 7D 00 )             // .Y.T:.{.0.}.IL_0059:  ldloc.0IL_005a:  callvirt   instance string CS30.Employee::get_Name()IL_005f:  call       void [mscorlib]System.Console::WriteLine(string,                                                                object)IL_0064:  nopIL_0065:  ldstr      bytearray (74 5E 84 9F 3A 00 7B 00 30 00 7D 00 )             // t^..:.{.0.}.IL_006a:  ldloc.0IL_006b:  callvirt   instance int32 CS30.Employee::get_Age()IL_0070:  box        [mscorlib]System.Int32IL_0075:  call       void [mscorlib]System.Console::WriteLine(string,                                                                object)IL_007a:  nopIL_007b:  ldstr      bytearray (1F 75 E5 65 3A 00 7B 00 30 00 7D 00 )             // .u.e:.{.0.}.IL_0080:  ldloc.0IL_0081:  callvirt   instance string CS30.Employee::get_BirthDate()IL_0086:  call       void [mscorlib]System.Console::WriteLine(string,                                                                object)IL_008b:  nopIL_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提供的语法级别的功能改进,是一种语法糖,是编写代码的效率更高,将一些重复性的工作交给编译器来做,但是这种改变,也增加了代码的不透明性,这点在隐式类型中体现的更为突出,增加了代码理解的难度,这些仅仅是提供给代码编写人员的一种选择,如果不喜欢也可以按照原来的方式来书写自己的代码也未尝不可。

时间: 2024-08-02 12:44:23

艾伟:C#3.0之自动属性和对象初始化器的相关文章

C#3.0之自动属性和对象初始化器

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

C#3.0中自动属性和对象初始化器

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

c#对象初始化器、自动实现字段

c#对象初始化器.自动实现字段 对象初始化器 在new对象的时候指定若干个成员为特定的值. 就是语法糖,相当于调用不带形参的构造函数后再挨个赋值. 例一 例二 自动实现字段 public int age { get; set; } 从功能上等价于 private int m_age; public int age { get { return m_age; } set { m_age = value; } } 也就是一开始的时候,先偷懒,写成 public int age { get; set;

C#3.0对象初始化器和集合初始化器

C# 3.0 中对象初始化器(Object Initializers) 和 集合初始化器(Collection Initializers) ,就是简化我们的代码,让本来几行才能写完的代码一行写完.这样在LINQ的使用中,我们才不会把一个LINQ表达式写的巨复杂无比. 由于我看到几篇讲 对象初始化器(Object Initializers)和集合初始化器(Collection Initializers) 的文章,都是一个简单的例子,一些稍稍特殊一点的场景的初始化赋值并没有涉及,所以我特整理这篇博客

C#3.0教程:自动属性和扩展方法

使用自动属性后,你可以不用手工声明一个私有成员变量以及编写get/set逻辑,取而代之的是,编译器会自动为你生成一个私有变量和默认的get/set 操作.系统为你产生的私有变量在IDE中,你是看不到的,如下图: 当然如果你希望属性中有些赋值或者取值逻辑校验,自动属性可是不适合你的. 上面的代码我们编译后,再用 Reflector 反编译后,我们可以看到上述代码中的属性变成了如下代码:这个编译器给我们产生的私有变量,显然不是那么容易重名的. [CompilerGenerated] private

.NET 3.x新特性之自动属性及集合初始化

今天公司弄了个VS2008 beta 2中文版,虽然很大一部分是为了JS的智能提示外,也应该好好的温习一下.NET的一些新特性,由于以前写过一些文章,但是都没有系统的学过,都只是尝一下新鲜感.不知道从那开始,所以今天就来看看自动话属性,以及对象初始化和集合初始化的一些新特性. 1.自动属性 在做一个程序是我们离不开属性,特别是实体类.我们用指头一个一个的敲着get和set及局部的变量(Fields),现在可好不用在重复敲那些东东了我们只要用到get和set,就和我们的接口声明差不多了,是不是很h

一起谈.NET技术,.NET 3.x新特性之自动属性及集合初始化

今天公司弄了个VS2008 beta 2中文版,虽然很大一部分是为了JS的智能提示外,也应该好好的温习一下.NET的一些新特性,由于以前写过一些文章,但是都没有系统的学过,都只是尝一下新鲜感.不知道从那开始,所以今天就来看看自动话属性,以及对象初始化和集合初始化的一些新特性. 1.自动属性 在做一个程序是我们离不开属性,特别是实体类.我们用指头一个一个的敲着get和set及局部的变量(Fields),现在可好不用在重复敲那些东东了我们只要用到get和set,就和我们的接口声明差不多了,是不是很h

.Net3.0中的自动属性(示例)

using System;namespace LinqDemo{    class Program    {        static void Main(string[] args)        {            //传统用法示例            Employee Emp = new Employee("Jimmy.Yang", 25);            Console.WriteLine(Emp.ToString());            Console

Linq之隐式类型、自动属性、初始化器、匿名类

目录 写在前面 系列文章 隐式类型 自动属性 初始化器 匿名类 总结 写在前面 上篇文章是本系列的小插曲,也是在项目中遇到,觉得有必要总结一下,就顺手写在了博客中,也希望能帮到一些朋友.本文将继续介绍linq系列的基础知识,隐式类型,自动属性,初始化器,匿名类的相关概念,这些内容也许与linq相关也许不相关,但还是放一起总结吧,也算是复习了.部分内容通过反编译的方式一探究竟. 系列文章 Linq之Lambda表达式初步认识 Linq之Lambda进阶 隐式类型 先看看Msdn上对隐式类型的简单定