属性(Property) 是类(class)、结构(structure)和接口(interface)的命名(named)成员。类或结构中的成员变量或方法称为 域(Field)。属性(Property)是域(Field)的扩展,且可使用相同的语法来访问。它们使用 访问器(accessors) 让私有域的值可被读写或操作。
首先搞清楚get和set有什么用,在面向对象编程里面,有的类的数据是私有的,是封装起来的,所以为了读取和写入对应的私有数据,c#采用了关键字get和set,其中get负责通过公共方法读取私有数据,set负责通过public方法写入private数据,但这两种用法应该并不绝对,我见过在get里面进行写入操作的。
我们在学习C#语法的属性时,都要首先和GET,SET访问器打交道,从英文的字面意思上理解,GET应该就是获得什么什么,而SET应该是设置什么什么,那我们看一下,官方是怎么定义这对访问器的:get是读取属性时进行的操作,set是设置属性时进行的操作。定义一个属性如果只有get,这个属性就是只读的。同样,只有set,属性就是只写的,当然只写的属性我觉的意义不是很大。
属性(Property)不会确定存储位置。相反,它们具有可读写或计算它们值的 访问器(accessors)。
例如,有一个名为 Student 的类,带有 age、name 和 code 的私有域。我们不能在类的范围以外直接访问这些域,但是我们可以拥有访问这些私有域的属性。
在程序中经常碰到get、set,不甚明白,在网上查询时也说的迷迷糊糊,所以整理下,以学的明白透彻点。
有两个类person:
public class person
{
public string name;
}
public class person
{
public string Name{set;get;}
}
第一个类型的name属性未封装,其name属性直接通过public关键字暴露给系统中的其他类了,而第二个类型的name属性通过get set关键字进行了封装,get和set分别对应的是可读和可写,相当于如下代码:
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
简单说下区别吧:当实例化第一个 “ person ” 这个类时,系统在分配内存空间时对 name 属性直接分配内存,之后对 name 属性的操作也是直接操作内存中 name 属性所在的这个块;而当实例化第二个“人”类型时,系统会先分配一个叫 name 的 private 私有的内存空间(此处的 name 对于类的内部使用,Name 对于外部操作使用,要有所区分),之后的读与写的操作都是通过 Name 这个 public 的类似于指针的东西来关联 name 进行,以此达到封装的目的,并且通过 get 和 set 关键字也可以控制可读还是可写。建议用后者,封装的好处可以参考相关文档,不再累述了~
至于get和set的作用,除了控制读写之外还有其他的作用,举个简单的例子,比如说当我给Name赋值的时候想要先进行一些逻辑判断,就可以这样:
private string name;
public string Name
{
get { return name; }
set { name = String.IsNullOrEmpty(value) ? "空" : value; }
}
再举例说明下:假设类是一银行,既能存钱也能取钱
class Bank
{
private int money;//私有字段
public int Money //属性
{
//GET访问器,可以理解成另类的方法,返回已经被赋了值的私有变量money
get { return money; }
//SET访问器,将我们打入的值赋给私有变量money
set { money = value; }
}
}
Money 就像银行里的自动取款机,你看不见里面的 money,但你能用set(存钱),用get(取钱)。
money是一个私有字段,是封装在类中的,类以外的程序不能直接访问的。C#中get、set用法中,类的set和get成员是外部程序访问类内部属性的唯一方法,就像你去银行取钱,你不能直接从银行的保险柜里拿钱,而是银行营业人员把钱取出来给你的。
我们设置了Money属性,怎么使用呢??
class Program
{
static void Main(string[] args)
{
//实例化一个Bank银行
Bank bank = new Bank();
//对Money属性做赋值操作,这时我们访问的是SET访问器
bank.Money = 15;
//对Money属性做取值操作,这时我们访问的是GET访问器
int a = bank.Money;
}
}
细心的朋友可以发现当我们设置断点在SET访问的中,执行代码 bank.Money = 15;时,就会进入我们属性中的SET访问器了。
以上就是我们的SET和GET访问器的最基本的应用了。
但是我们为什么要用GET和SET访问器呢??
通过GET和SET对公有变量Money进行读写操作,实际就是间接更改money私有变量的值,那既然如此。为何不设money为public,让实例直接对money进行读写操作呢?我们是不是在多此一举呢?
其实,我当初刚接触GET和SET就很理解,并不是说他们的含义难理解,而是为什么要用?为何不直接用个public的字段变量来代替呢?
理解一:用了GET和SET能让赋值和取值增加限制
class Bank
{
private int money;//私有字段
public int Money //属性
{
//GET访问器,可以理解成另类的方法,返回已经被赋了值的私有变量 money
get { return money; }
//SET访问器,将我们打入的值赋给私有变量 money,并且加了限制,不能存负的
set
{
if (value >= 0)
{
money = value;
}
else
{
money = 0;
}
}
}
}
这样的话,我们是永远无法给Money属性赋值负的金钱了!
其实这种应用才是我们的实际的项目中,属性设置中非常常见!例:
public string ApplyStaff
{
//延迟加载ApplyStaff对象
get
{
if (this.IsGhost)
{
LazyLoaderFactory.GetLoader().LoadApplicationConfirm(this);
}
return applyStaff;
}
set
{
//判断输入的字符的长度
if (value.Length > 40)
{
throw new Exception("领用人不能超过40个字符。");
}
this.applyStaff = value;
}
}
public string BillName
{
get
{
return billName;
}
set
{
if (value==string.Empty)
{
throw new Exception("单据名称不能为空");
}
else if (value.Length > 40)
{
throw new Exception("单据名称长度不能超过40个字符");
}
else
{
this.billName = value;
}
}
}
如果在SET访问器中设置这个属性的一些特性,比如说不能为空,长度大小,必须为数字,各类正则表达式等等,然后抛出异常,表示层再来接受,这样就可以少写很多验证程序了。
属性在调用者看来就像一个普通的变量,但作为类的设计者,你可以利用属性来隐藏你类中的一些字段,使外界只能通过属性来访问你的字段,你可以通过属性来限制外界对你的字段的存取,就利用get、set。如果想让用户随意存取你的字段,那么就实现get、set;如果只想让用户读取字段,就只实现get;若只想让用户写字段就只实现set。同时还可以在set和get中对用户传递的值进行一些验证工作,以确保你的字段将含有正确的值。
Private int a;
Public int index
{
get { return a; }
set {
If (value>0) a=value;
else a=0; }
}
可看出,get、set用法中
一则是隐藏组件或类内部的真实成员;
二是用来建立约束的,比如,实现“有我没你”这种约束;
三是用来响应属性变化事件,当属性变化是做某事,只要写在set方法里就行。
当你想读出或写入属性的值时,存取标志限定了被实现的语句。用于读出属性的值的存取标志记为关键字get,而要修改属性的值的读写符标志记为set。