一、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