關於.Net中屬性的使用探討(二) (轉)

amyz發表於2007-08-16
關於.Net中屬性的使用探討(二) (轉)[@more@]

關於中屬性的使用探討(二)

codeprince 

三.編寫Get過程中需要注意的問題

  當定義一個標量屬性的時候,如上面所定義的CityName,這是一個既可讀又可寫的屬性,當然你可以將它定義為只讀的屬性。我們需要考慮如何去編寫get過程。(更多的人是和我開始的時候一樣,什麼都不做,寫一個return語句,我要說這是的,但我們還需要了解其他一些東西)。我要說的第一個問題是:Get不應該有任何明顯的副作用,換句話說,你對Get過程的定義不能影響到這個類的狀態,比如說你編寫CityName這個屬性,但你又想透過CityName反映城市與城市之間的某種關係,這樣就會增加CityName的副作用,這是不好的行為。為什麼呢?這是因為Get過程在邏輯上與訪問欄位類似,如果我們發現了自己在Get函式中了狀態,那麼我的建議(也是Andy Olsen等專家的建議)是將這個Get過程實現為方法。方法是可以也是經常會產生副作用的。

  也許有人會說既然這樣,方法不是可以取代屬性了嗎,還要它幹嗎?這本身就是一種替代和包含的關係嗎!其實有的時候我也這麼想,但我要說有三種情況也許會打動你的心從而使用屬性。

1.  要獲取類中現有的欄位值。在這種情況下,Get函式只作為已經在類中出現的一塊資料的包裝器。Get函式直接返回私有欄位的值。(這也是我們最為經常遇到的)

2.  要計算類中的派生值。在這種情況下,Get過程使用類中的資料來計算新的值,對於物件導向的分析和設計來說,這叫做類的派生特性。

3.  要“懶惰”初始化。(也就是推遲初始化類中的私有欄位)在這種情況下,類有一個很少使用的欄位,或者說有些欄位在建立物件時,你無法預計它的值(當然由可以指派一個預設的值),為了,我們可以推遲初始化這個欄位,直到它透過Set過程(或其他的方法顯示地賦值)。當需要這個欄位時,我們再透過Get過程得到。如果客戶應用永遠不請求這個欄位,那麼我們也就永遠不用計算它,這樣就提高了。

下面分析一個例子:

  Class City

  private mCityName as String  '城市的名稱

  private mBuildTime as DateTime  '城市的修建時間

  private  mChargedRegionSquares as String '城市所管轄的地域面積

  public Sub New(Byval CityName as String,Byval BuildTime as DateTime)

  mCityName=CityName

  mBuildTime=CityHistory

  mChargedRegionSquares=""

  End Sub

  public Property CityName() as String

  Get

  Return mCityName

  End Get

  Set(Byval Value as String)

  mCityName=Value

  End Set

  End Property

  'CityHistory屬性代表了城市已存在的時間
  Public ReadOnly Property CityHistory() as Integer 

  Get

 Dim Today as DateTime=DateTime.Now

  Dim Years as Integer=DateTime.Now.Year-mBuildTime.Year

  if (Today.Month

 (Today.Month=mBuildTime.Month and

 Today.Day

  Years-=1

  End If

  Return Years

  End Get

  End Property

  public ReadOnly Property ChargedRegionSquares() as String

  Get

  if (mChargedRegion="" then

  Dim Conn as OleConnection

  Dim Cmd as OleDbCommand

  Try

  Conn=New OleDbConnection("Provr=........."&_

  "Data=City.mdb")

  Cmd=New OleDbCommand(" RegionSquares From

 CityRegions Where CityName='"&mName&"'",

  Conn)

  mChargedRegionSquares=Cmd.ExecuteScalar()

  if mCharedRegionSquares is Nothing then

  mChargedRegionSquares=""

  end If

  Catch Ex as OleDbException

 Console.Writeln("Error occurred:{0}",Ex.Message)

  Finally

  if Not Conn is Nothing Then

  Conn.Close()

  End If

  End Try

 End If

  Return mChargedRegionSquares

  End Get

  End Property

  End Class

我們現在來分析上面的程式碼:(對於上面的程式碼中用到了的連線,需要我們顯示地Imports System.Data.OleDb,這是必須的。)

1.  City類有表示城市的名稱,城市的修建時間,城市的管轄地域這三個私有欄位。

2.  建構函式初始化城市的名稱和城市的修建時間這兩個私有欄位,並且將城市的管轄地域初始化為,用來指示將在第一次讀取資料庫時被讀取到。

3.  CityName屬性獲取和設定mCityName欄位,而沒有更深的處理,這個屬性很薄地封裝了mCityName的屬性。

4.  CityHistory屬性根據城市的修建時間和當前的時間來計算這個城市的存在時間。這是一個很明顯的派生特性的例子。注意:每次都重新計算CityHistory似乎比把這個時間存在欄位裡要合適的多。

5.  ChargedRegionSquares屬性可以進行懶惰初始化。在上面的例子中,城市管轄的地域存在資料庫中,所以我們在建構函式中就不要對它求值,因為這樣就可以當客戶程式碼需要用到這個屬性時,就與資料庫連線來獲得。這樣明顯提高了效率。

6.  我們在上面的程式碼中加入了錯誤和異常的處理,這對於一個健壯的物件導向的程式來說是必要的,相信大家和我有同感吧。

 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752019/viewspace-962731/,如需轉載,請註明出處,否則將追究法律責任。

相關文章