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