2012年6月26日 星期二

C# 物件配置與記憶體議題

對於實值型別(等同Java中稱的基本型別)一樣是放在stack
在method中也同樣是以複製的形式傳遞
也就是method中作的變動不會影響到原本的實值型別物件
不過若要改變傳遞的形式則可以使用 ref、out 兩個關鍵字

ref的用法為宣告使用call by reference
如:public void swap(ref int x, ref int y){ ... //code for swap x&y }


使用method時亦用ref,如:

int a = 1;    int b = 2;
swap(ref a, ref b);


如此一來a與b的值就會在method呼叫過後改變了
C#在配置物件(參考型別資料)時亦隱含了ref的宣告
所以省略不寫也沒關係
但若明白的了ref宣告
則必須在參數、引述的地方都宣告,否則會引起編譯錯誤,如:

public void dosth(ref int[,] intary){ .... }

int[,] a = new int[]{{1,2},{3,4}}
dosth(ref a);     //如果參數、引數只有其中一方宣告ref會引起錯誤


out關鍵字的作用則是傳出值,如:
public void assignValue(out int x, out int y){
    x = 6;  y = 10;                //必須在method中宣告值
.........
}

int a; int b;                           //未賦予初始值
assignValue(out a, out b);    //此時a = 6, b = 10


不過用法雖然多樣化了,但似乎連Visual Studio Team也不鼓勵ref、out的使用
畢竟若設計師不熟悉用法則容易出錯
一般是建議找替代方法來達成目標

struct的使用可以參考MSDN上的說明-使用結構
使用上有無法繼承與多型的限制,但在僅用來儲存field時會有較class更好的效能
其記憶體配置也是位在stack
所以指派的時候也是使用複製,等同於創造出新的struct
注意這點以避免疏失
而struct作為參數傳遞時,可考慮使用ref,以優化性能(當然這時候要注意值的變化)

C#的class有時候並不提供擴展,如第三方的類別等
要封裝類別只要在class宣告前加入sealed關鍵字,如:sealed class ap{...}
如果打算擴展這些類別,C#提供如下作法:

static class secondAp{
    public static string getAns(this ap apobj, double fi1){...}
}


擴張方法必須是存在於靜態類別中的靜態方法
this ap 指定擴充ap類別

沒有留言:

張貼留言