C#的“属性”封装
C#和delphi一样,拥有“属性”这一个概念。使用惯了c/c++,刚开始接触类型属性还真有点不是很适应。C#中“属性”具体的用法如下:
class Employee
{
private int empID;
private float currPay;
private string empName;
private int empAge;
public int Age
{
get { return empAge;}
set { empAge = value; }
}
public Employee() { }
public Employee(string name, int age, int id, float pay)
{
empName = name;
empID = id;
empAge = age;
currPay = pay;
}
}
这里,Age相当于Employee中的一个的“属性”,我们可以认为它是内部私有成员empAge的一个“别名”,它起到了两个作用:1.隐藏了内部的私有成员变量 2.简练的完成了设置set和获得get私有变量的功能。以前在c++中实现上面获取/修改成员变量的功能的时候,我们可能会更多的使用set***() 和get***()的方法。但是在c#里面,还是强烈推荐使用属性来完成对用的成员变量的操作。
当我们使用上面的类型属性机制,要修改私有成员变量empAge,那么可以写为:
Employee joe = new Employee();
Joe.Age = 50; // 老员工
注意点:
运行vs的附加工具ildasm,载入刚才编译好的代码employeev.exe,我们可以非常清楚的看到employee类里面的age属性实际上是被映射到CLR内部调用的get_Age()以及set_Age(int32 )的方法,CLR再一次为我们程序员解放劳动生产力做出了杰出的贡献。(感谢大神Anders Hejlsberg )
所以,当我们编写好了age属性,试图再编写set,get方法的时候:
public int get_Age()
{
return empAge;
}
public void set_Age(int age)
{
empAge = age;
}
Csc编译器是不会放过你的:
当然了,你写成
public int get_age()
{
return empAge;
}
public void set_age(int age)
{
empAge = age;
}
编译器还是会允许你冗余的制造代码的。
所以,我们可以得出结论:
当我们只是编制了类似Age之类的 类型属性之后,clr会自动的映射到它生成的set_属性名、get_属性名方法 ,所以当你自以为是的显示编制了同名的 set_属性名()、get_属性名()之后,编译器会提示错误。画蛇添足的事情还是少干为好,毕竟c#在背后已经为我们默默完成了很多实用的功能。
在这里,不禁又生出一个疑问:在c#里,对象中“属性”的内存布局又是怎么样的呢?它的实际开销又有多大呢?值得继续研究…..