程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> Effective C#原則6:區別值類型數據和引用類型數據(2)

Effective C#原則6:區別值類型數據和引用類型數據(2)

編輯:關於C語言

現在,v是原始數據_myData的一個COPY 。做為一個引用類型,兩個對象都是在內存堆上創建的。你不會因為暴露內部數 據而遇到麻煩。取而代之的是你會在堆上建立了一個額外的數據對象。如果v是 局部變量,它很快會成為垃圾,而且Clone要求你在運行時做類型檢測。總而言 之,這是低效的。

以公共方法或屬性暴露出去的數據應該是值類型的。 但這並不是說所有從公共成員返回的類型必須是值類型的。對前面的代碼段做一 個假設,MyData有數據存在,它的責任就是保存這些數據。

但是,可以 考慮選擇下面的代碼段:

private MyType _myType;
public IMyInterface Foo()
{
return _myType as IMyInterface;
}
// call it:
IMyInterface iMe = Foo();
iMe.DoWork( );

變量_myType還是從Foo方法返回。但這次不同的是,取而代之 的是訪問返回值的內部數據,通過調用一個定義好了的接口上的方法來訪問對象 。你正在訪問一個MyType的對象,而不是它的具體數據,只是使用它的行為。該 行為是IMyInterface展示給我們的,同時,這個接口是可以被其它很多類型所實 現的。做為這個例子,MyType應該是一個引用類型,而不是一個值類型。MyType 的責任是考慮它周圍的行為,而不是它的數據成員。

這段簡單的代碼開 始告訴你它們的區別:值類型存儲數據,引用類型表現行為。現在我們深入的看 一下這些類型在內存裡是如何存儲的,以及在存儲模型上表現的性能。考慮下面 這個類:

public class C
{
 private MyType _a = new MyType( );
 private MyType _b = new MyType( );
 // Remaining implementation removed.
}
C var = new C ();

多少個對象被創建了?它們占用多少內存?這還不好說。如 果MyType是值類型,那麼你只做了一次堆內存分配。大小正好是MyType大小的2 倍。然而,如果MyType是引用類型,那麼你就做了三次堆內存分配:一次是為C 對象,占8字節(假設你用的是32位的指針)(譯注:應該是4字節,可能是筆誤), 另2次是為包含在C對象內的MyType對象分配堆內存。之所以有這樣不同的結果是 因為值類型是以內聯的方式存在於一個對象內,相反,引用類型就不是。每一個 引用類型只保留一個引用指針,而數據存儲還須要另外的空間。

為了理 解這一點,考慮下面這個內存分配:

MyType [] var = new MyType[ 100 ];

如果MyType是一個值類型數據,一次就分配出 100個MyType的空間。然而,如果MyType是引用類型,就只有一次內存分配。每 一個數據元素都是null。當你初始化數組裡的每一個元素時,你要上演101次分 配工作--並且這101次內存分配比1次分配占用更多的時間。分配大量的引用類型 數據會使堆內存出現碎片,從而降低程序性能。如果你創建的類型意圖存儲數據 的值,那麼值類型是你要選擇的。

采用值類型數據還是引用類型數據是 一個很重要的決定。把一個值類型數據轉變為類是一個深層次的改變。考慮下面 這種情況:

public struct Employee
{
 private string _name;
 private int   _ID;
 private decimal _salary;
 // PropertIEs elided
 public void Pay( BankAccount b )
 {
  b.Balance += _salary;
 }
}

這是個很清楚的例子,這個類型包含一個方法,你可以用它 為你的雇員付薪水。時間流逝,你的系統也公正的在運行。接著,你決定為不同 的雇員分等級了:銷售人員取得擁金,經理取得紅利。你決定把這個Employee類 型改為一個類:

public class Employee
{
 private string _name;
 private int   _ID;
 private decimal _salary;
 // PropertIEs elided
 public virtual void Pay( BankAccount b )
 {
  b.Balance += _salary;
 }
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved