一、get、set 的基本简介
在面向对象编程(OOP)中,是不允许外界直接对类的成员变量直接访问的,既然不能访问,那定义这些成员变量还有什么意义呢?所以C#中就要用set和get方法来访问私有成员变量,它们相当于外界访问对象的一个通道,一个“接口”。先来看一段代码:
class Employee { private string name; private byte age; public string Name { get { return name; } set { name = value; } } public byte Age { get { return age; } set { age = value; } } }
代码中定义了两个私有变量name和age,当我们不想让外界随意访问该私有变量时,可以使用属性来访问,语法为:
public <返回类型(要与被访问变量的类型相同)> <属性名(不能与被访问变量同名)> { get{ return <被访问变量>;} set{ <被访问变量> = value;} }
当我们使用属性来访问私有成员变量时就会调用里面的get方法,当我们要修改该变量时就会调用set方法,当然在定义的时候可以只定义一个get方法或只定义一个set方法。如果只定义get方法,那么这个相应变量就是“只读”的;如果只定义set方法,那么相应变量就是“只写”的。
既然外界可以通过set和get访问类内私有成员,那为什么不直接把它定义成共有,直接供外界访问呢?拿上面的Employee类来说明:
class Employee { private string name; private byte age; public string Name { get { return name; } set { name = value; } } //****修改后****↓↓↓↓↓↓↓↓ public byte Age { get { return age; } set { if (value > 10 && value<=100) //一般在公司雇员的年龄都在10到100岁之间 age = value; } } //****修改后****↑↑↑↑↑↑↑↑ }
上例中,set就像一位门卫大叔一样,只有好人才能进来。可以通过属性来控制对员变量的读写,防止对成员变量的非法赋值等。
再举个小例子,以下是个温度计的类:
class Thermometer { private double temperature; public Thermometer(double temperature) //构造函数 { this.temperature = temperature; } public double Temperature { get { return temperature; } set { temperature = value; } } }
假设这里的温度单位表示的是摄氏度(℃),如果在需求分析阶段误解了客户的原始意愿或者客户在日后变更了需求,需要把系统中所有表示温度的变量temperature都用来表示开尔文温度(K)。那么不必动系统中成百上千个Temperature属性,只需在get和set函数中稍微修改一下代码即可:
class Thermometer { private double temperature; public Thermometer(double temperature) //构造函数 { this.temperature = temperature; } public double Temperature { //****修改后****↓↓↓↓↓↓↓↓ get { return temperature-273.15; } set { temperature = value+273.15; } //****修改后****↑↑↑↑↑↑↑↑ } }
建一个控制台应用程序来测试一下,主函数为:
class Test { static void Main(string[] args) { Thermometer a = new Thermometer(40); Console.WriteLine(a.Temperature); } }
上面代码中用构造函数给温度设的初值为40度,代码修改前运行结果为“40”,代码修改后运行结果为“-233.15”。
_____________________________________________________________________________________________________________________________________________________________
二、实例说明
1、person类举例如下:
public class person1 { public string name; } public class person2 { public string Name{set;get;} }
第一个类型的name属性未封装,其name属性直接通过public关键字暴露给系统中的其他类了。而第二个类型的name属性通过get和set关键字进行了封装,get和set分别对应的是可读和可写。由于其除了可读可写外,没有其它的条件限制操作,所以相当于如下代码:
// 字段:一般为私有的,不对外开放 private string name; // 属性:一般为公有的,作为外部访问对应字段的一个接口 public string Name { get { return name; } //相当于通过Name来返回name的值 set { name = value; } //通过Name来设置name的值 }
* 以上的不同写法的区别:
- 当实例化第一个“人 -person1-”这个类时,系统在分配内存空间时对name属性直接分配内存,之后对name属性的操作也是直接操作内存中name属性所在的这个块
- 当实例化第二个“人”类型时,系统会先分配一个叫name的private私有的内存空间,之后的读与写的操作都是通过Name这个public的类似于指针的东西来关联name进行,以此达到封装的目的,并且通过get和set关键字也可以控制可读还是可写。建议用后者。
2、至于get和set的作用,除了控制读写之外还有逻辑、条件判断的作用。例如当给Name赋值的时候想要先进行一些逻辑判断,就可以这样:
private string name; public string Name { get { return name; } set { name = String.IsNullOrEmpty(value) ? "空" : value; } }
3、再举例说明下
class Test { private int age; public int Age { get { return age; } set { if (value < 0 || value > 200) { Console.WriteLine("无效的赋值,年龄必须在0——200之间"); } else { age = value; } } } }
C#中get、set用法中,类的set和get成员是外部程序访问类内部属性的唯一方法,就像你去银行取钱,你不能直接从银行的保险柜里拿钱,而是银行营业人员把钱取出来给你的。
属性在调用者看来就像一个普通的变量,但作为类的设计者,你可以利用属性来隐藏你类中的一些字段,使外界只能通过属性来访问你的字段,你可以通过属性来限制外界对你的字段的存取,就利用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; } }
4、可看出,get、set用法有如下特点:
- 一则是隐藏组件或类内部的真是成员;
- 二是用来建立约束的,比如,实现“有我没你”这种约束;
- 三是用来响应属性变化事件,当属性变化是做某事,只要写在set方法里就行;
当想读出或写入属性的值时,存取标志限定了被实现的语句。用于读出属性的值的存取标志记为关键字get,而要修改属性的值的读写符标志记为set。
三、最新简化使用方法
对于只是限定读取和访问权限,而无复杂逻辑条件判断的,可以使用一些简化的方式。
1、原始写法
// 写法一 class Test { private int age; public int Age { get { return age; } set { age = value; } } } // 写法二 class Test { private int age; public int Age { get => age; set => age = value; } }
2、简化写法
class Test { public int Age { get; set; } //或者直接省略 public int Name; }
文章转载自:http://blog.csdn.net/u013095889/article/details/52804360