c#

位置:IT落伍者 >> c# >> 浏览文章

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


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

匿名属性

定义属性如下

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# 之前的写法如下

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; }

}

}

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

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

对象初始化器

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

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

Employee employee = new Employee { Id = Name = 蓝之风 Age = BirthDate =

Sex = };

ConsoleWriteLine(编号;{} employeeId);

ConsoleWriteLine(姓名:{} employeeName);

ConsoleWriteLine(年龄:{} employeeAge);

ConsoleWriteLine(生日:{} employeeBirthDate);

ConsoleWriteLine(性别:{} employeeSex);

ConsoleWriteLine(请按任意键继续);

ConsoleReadLine();

这句

Employee employee = new Employee { Id = Name = 蓝之风 Age = BirthDate =

Sex = };

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

在C#之前的做法是

Employee employee = new Employee();

employeeId = ;

employeeName = 蓝之风;

employeeAge = ;

employeeBirthDate = ;

employeeSex = ;

ConsoleWriteLine(编号;{} employeeId);

ConsoleWriteLine(姓名:{} employeeName);

ConsoleWriteLine(年龄:{} employeeAge);

ConsoleWriteLine(生日:{} employeeBirthDate);

ConsoleWriteLine(性别:{} employeeSex);

ConsoleWriteLine(请按任意键继续);

ConsoleReadLine();

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

method private hidebysig static void Main(string[] args) cil managed

{

entrypoint

// 代码大小 (xaf)

maxstack

locals init ([] class CSEmployee employee

[] class CSEmployee <>g__initLocal)

IL_: nop

IL_: newobj instance void CSEmployee::ctor()

IL_: stloc

IL_: ldloc

IL_: ldci

IL_: callvirt instance void CSEmployee::set_Id(int)

IL_e: nop

IL_f: ldloc

IL_: ldstr bytearray (DD B E CE ) // KN

IL_: callvirt instance void CSEmployee::set_Name(string)

IL_a: nop

IL_b: ldloc

IL_c: ldcis

IL_e: callvirt instance void CSEmployee::set_Age(int)

IL_: nop

IL_: ldloc

IL_: ldstr

IL_a: callvirt instance void CSEmployee::set_BirthDate(string)

IL_f: nop

IL_: ldloc

IL_: ldstr bytearray ( ) // u

IL_: callvirt instance void CSEmployee::set_Sex(string)

IL_b: nop

IL_c: ldloc

IL_d: stloc

IL_e: ldstr bytearray ( F F B B D ) // S;{}

IL_: ldloc

IL_: callvirt instance int CSEmployee::get_Id()

IL_: box [mscorlib]SystemInt

IL_e: call void [mscorlib]SystemConsole::WriteLine(string

object)

IL_: nop

IL_: ldstr bytearray (D D A B D ) // YT:{}

IL_: ldloc

IL_a: callvirt instance string CSEmployee::get_Name()

IL_f: call void [mscorlib]SystemConsole::WriteLine(string

object)

IL_: nop

IL_: ldstr bytearray ( E F A B D ) // t^:{}

IL_a: ldloc

IL_b: callvirt instance int CSEmployee::get_Age()

IL_: box [mscorlib]SystemInt

IL_: call void [mscorlib]SystemConsole::WriteLine(string

object)

IL_a: nop

IL_b: ldstr bytearray (F E A B D ) // ue:{}

IL_: ldloc

IL_: callvirt instance string CSEmployee::get_BirthDate()

IL_: call void [mscorlib]SystemConsole::WriteLine(string

object)

IL_b: nop

IL_c: ldstr bytearray ( B A B D ) // `+R:{}

IL_: ldloc

IL_: callvirt instance string CSEmployee::get_Sex()

IL_: call void [mscorlib]SystemConsole::WriteLine(string

object)

IL_c: nop

IL_d: ldstr bytearray (F B FB E F E E E ED E E // cNa~~

E E ) //

IL_a: call void [mscorlib]SystemConsole::WriteLine(string)

IL_a: nop

IL_a: call string [mscorlib]SystemConsole::ReadLine()

IL_ad: pop

IL_ae: ret

} // end of method Program::Main

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

总结

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

               

上一篇:C#判断素数的算法

下一篇:Visual Basic.Net实现TCP协议