這是最近在想的一個(gè)問題,使用getter,setter的好處是什么? 但實(shí)際上,我在搜索的過程中,看到了很多“反對(duì)”的聲音。
先復(fù)習(xí)一下,什么是getter,setter.
在C#中,我們又稱它為property(屬性),它是一組setter,getter的訪問器(accessor),是一個(gè)函數(shù)成員。
在使用上,就像是在調(diào)用公共的字段一樣,但它是函數(shù),不分配內(nèi)存。
set訪問器為屬性賦值。擁有一個(gè)單獨(dú)的,隱式的值參,名為value,與屬性的類型相同。返回類型為void.
get訪問器從屬性獲取值。沒有參數(shù),擁有一個(gè)與屬性類型相同的返回類型。get訪問器返回一條return語句。
setter,getter可以任意順序聲明,并且,除了這兩個(gè)訪問器外,不允許有其它的方法。
如:
private stringcristiano;
public string Cristinao{
set{ cristiano = value; }
get{ return cristiano; }
age{...}//error
}
屬性常和字段進(jìn)行關(guān)聯(lián),字段通常設(shè)置為private(這通常叫”后備字段“),因?yàn)槊嫦驅(qū)ο蟮脑O(shè)計(jì)的重要原則之一就是數(shù)據(jù)封裝,意味著類型的字段永遠(yuǎn)不應(yīng)該被公開,否則很容易被不恰當(dāng)?shù)氖褂米侄味茐牧藢?duì)象的狀態(tài),如:xxx.age-=5;是不合理的,所以,要通過函數(shù),來對(duì)保護(hù)的字段進(jìn)行讀寫。(很像代理設(shè)計(jì)模式:))
在屬性中,可以做很多邏輯上的計(jì)算,比如:
private int money;
public int Money{
set{
money = value < 100 ? 100 : value;
}
get{
return money < 100 ? 100 : money;
}
}
屬性始終是函數(shù)成員。
getter,setter并不需要同時(shí)定義,只包含getter的屬性,只能讀取,而不能寫入,相反,只包含setter的屬性,只能寫入,不能讀取,但兩者必須至少定義一個(gè)。
自動(dòng)實(shí)現(xiàn)屬性
因?yàn)閷傩越?jīng)常被關(guān)聯(lián)到”后備字段“,C#提供了自動(dòng)實(shí)現(xiàn)屬性(AIP),允許只聲明 屬性 而不需要聲明 后備字段
,編譯器會(huì)為你隱藏的創(chuàng)建一個(gè)私有的字段,并且自動(dòng)掛接到get和set訪問器上(accessor)
如:
public string Messi {
set;
get;
}
如果其中一個(gè)訪問器提供了方法體,另一個(gè)也需要。
public static string Russia {
set;
get;
}
什么時(shí)候應(yīng)該使用字段?
1.你希望返回字段來執(zhí)行一些其它的副作用,比如緩存某個(gè)值(currentState,PreviousState)
2.你希望以線程安全的方式來訪問字段
3.這是一個(gè)邏輯的字段,需要計(jì)算來獲得,如面積area.
基礎(chǔ)說完了,那么以上面定義的Russia為例,他和常規(guī)定義一個(gè)set,get函數(shù)有什么優(yōu)勢(shì)呢?
private string russia;
public void SetRussia(string val)
{
russia = val;
}
public string GetRussia()
{
return russia;
}
首先:
最直觀的是屬性/訪問器比常規(guī)函數(shù),代碼上更加的簡(jiǎn)潔了,無論是定義上,還是使用上。
但僅僅就是這些嗎,所以常規(guī)操作,去stackoverflow上找找大神們的回復(fù),但意外的是,有很多人抨擊accessor的設(shè)計(jì)是evil.有興趣可以看下面的鏈接:
https://www.javaworld.com/article/2073723/core-java/why-getter-and-setter-methods-are-evil.html
CLR via C#的作者也對(duì)accessor的設(shè)計(jì)嗤之以鼻,不過他提到AIP自動(dòng)屬性無法調(diào)試和序列化&反序列化是不準(zhǔn)確的,也許和他的應(yīng)用環(huán)境有關(guān),我在Mono里測(cè)試,都是OK的:)
具體關(guān)于getter,setter的討論可以看這篇(很精彩):
https://stackoverflow.com/questions/1568091/why-use-getters-and-setters-accessors
有的人說,setter/getter,讓代碼不易于閱讀,你無法直接判斷是共公的字段還是屬性。
使用常規(guī)自定義的setxx/getxxx,具有更好的移植性。
屬性/訪問器,除了在使用和定義上,相比常規(guī)函數(shù)要更簡(jiǎn)潔以外,它通常于需要做一些額外操作的情況,比如校驗(yàn),保存舊的值,做一些邏輯上的計(jì)算等等,如果僅僅是返回源引用的形式,意義并不大。大多數(shù)情況下,我們還是要使用自定義參數(shù)的函數(shù)來適應(yīng)各種復(fù)雜的場(chǎng)景。(2018.9.10 更新)
參考資料:
C#圖解教程
CLR via C#
寫得有些倉促,后面看到相關(guān)的會(huì)繼續(xù)補(bǔ)充上來,2點(diǎn)15分了,時(shí)間過得太快,肚子又餓了,一堆任務(wù)壓著沒有完成,現(xiàn)在休息,早起繼續(xù)工作!