工作前期,是在熟悉组里的代码,很基础的get set,却被我的同事们写出了许多花样,于是研究了一番。
一、属性访问器的基本写法
(1)自动属性
<span style="font-family:Microsoft YaHei;font-size:14px;">class Test
{
public int Num{get; set;}
}</span>
(2)标注写法
<span style="font-family:Microsoft YaHei;font-size:14px;">class Test
{
private int _num;
public int Num
{
get
{
return _num;
}
set
{
_num = value;
}
}
}</span>
(3)只读属性
<span style="font-family:Microsoft YaHei;font-size:14px;">class Test
{
private int _num;
public int Num
{
get
{
return _num;
}
}
}</span>
(4)只写属性
此处想和网友们探讨,只写属性的作用是啥?我现在还不太清楚。。。。。(反正有这种写法)
<span style="font-family:Microsoft YaHei;font-size:14px;">class Test
{
public int Num{set;}
}</span>
如上,是属性选择器最为基础的写法,(1)和(2)的区别在于(1)是(2)的简写,方便属性过多时候,对于程序员编程效率的提升。通过Visual Studio的编译器,写法(1)会被编译为写法(2)的代码,虽然此时(1)和(2)没有区别,若是要改变get或者set的修饰符权限,就只能使用(2)这种写法,这一点一会儿会做以讨论。对于(3)和(4),分别是只读属性和只写属性,具体用在哪里我还缺少实战经验,总之了解到了有这样子的写法。
二、属性访问器的一些理解
(1)为什么使用属性访问器?
在不使用get、set的时候,一个类,会有成员变量(.net里的全局变量)以及局部变量,外界方法对于该类的成员变量进行访问,对于局部变量不能够访问,即使能够访问,外部的方法不能够修改它,怎么办?使用了get和set属性之后,就像是为类加入了一个“门神”,访问和修改都会有所过滤,看该看的,改可以修改的,在安全性上有了提升。我的理解就是这样。
(2)属性访问器用在哪里?
项目中,更多的会用在实体当中,然而实体这部分代码看起来更像是”静态”的代码,被活跃的“业务逻辑”代码所使用,匹配数据类型,类似于:
<span style="font-family:Microsoft YaHei;font-size:14px;">public void Test()
{
Model shili = new Model();
shili.Shuxing = a //赋值操作
}</span>
这个“对象名.属性=“值”的语句,实质上就是在调用set语句,与之对应“变量 = 对象名.属性”的语句,实质上就是在调用get语句。
三、属性访问器的高级用法
(1)定义不同的访问修饰符
<span style="font-family:Microsoft YaHei;font-size:14px;">public string Name
{
get
{
return _name;
}
protected set
{
_name = value; //外层public,内层protected
}
}
</span>
如上,对Name这个属性,类外的方法,可以获取其中的值,但是不允许外部赋值(除非是子类哦~protected)
<span style="font-family:Microsoft YaHei;font-size:14px;">protected string Name //外层protected
{
public get { return _name; } //外层protected,内层public
set { _name = value; }
}
</span>
如果,外层的修饰符范围比内层的小,这种写法就错误了。So,1.外层访问修饰符要大于内层,2.外层属性的修饰符一定要写出来,不要省略。(2)属性加验证
<span style="font-family:Microsoft YaHei;font-size:14px;">public string Name
{
get
{
return name != null ? name : "NA";//get属性的时候,如果name变量为null值,返回'NA',否则返回name值
}
}
</span>
这个例子是取值时候加以验证,从而不至于出现因返回值为空引起的错误。
<span style="font-family:Microsoft YaHei;font-size:14px;">private int money;
public int Money
{
get { return money; }
//增加限制,存钱不能为负数
set
{
if (value >= 0) {
money = value;
}
else {
money = 0;
}
}
}
</span>
第二个例子,则是对于属性赋值时的健壮性操作,确保数据范围正确。
(3)get set之间的集成使用
<span style="font-family:Microsoft YaHei;font-size:14px;">abstract class A
{
int y;
public virtual int X
{
get
{ return 0; } //对于X属性,只能读取,不能赋值
}
public virtual int Y
{
get { return y; }
set { y = value; } //对于Y属性,读取和赋值都可以
}
public abstract int Z { get; set; } //抽象类中的抽象属性,必须被继承
}
class B: A
{
int z;
public override int X
{
get { return base.X + 1; } //通过base引用父类中的属性值
}
public override int Y
{
set //仅仅通过set便覆盖了类A中的虚属性
{
base.Y = value < 0? 0: value;
}
}
public override int Z
{
get
{
return z;
}
set
{
z = value;
}
}
} </span>
这个例子集中地展示了属性在继承上下文中的某些典型行为。这里,类A由于抽象属性Z的存在而必须声明为abstract。子类B中通过base关键字来引用父类A的属性。类B中可以只通过Y-set便覆盖了类A中的虚属性。That's all.