因為數值類型的分類是值類型和引用類型,是以方法的參數也有這兩種類型。
值類型參數:
static void Main()
{
int i=1;
Mehtod(i);
}
static void Method(int s)
s=200;
如果方法的參數是值類型,調用者Main傳遞給被調用方法Method的是一個值類型的副本,即i的一個副本,i與方法Method中的s值相同,但一旦調用完畢兩都就沒有關系了。
引用類型:
int[] arri=new int[]{1};
Method(arri);
static void Method(int[] arrs)
Arrs[0]=200;
引用類型作為方法的參數時,調用者傳遞的是引用(與指針類似),即把arri數組的引用傳給Method方法,這裡隻是把引用傳遞給方法,而非副本,這點就使在Main中的arri與在Method中的arrs引用的是同一個對象,在兩個方法的任何地方使之改變都會影響另一個方法的資料的。
簡單的說,值類型參數傳遞副本,引用類型參數傳遞引用。
接下來說說ref和out作為參數
先看一下下面的代碼,
static void F1(ref int i)
{
i = 100;
}
static void F2(out int i)
看看這兩個方法對應的IL
.method private hidebysig static void F1(int32& i) cil managed
// 代碼大小 6 (0x6)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.s 100
IL_0004: stind.i4
IL_0005: ret
} // end of method Program::F1
.method private hidebysig static void F2([out] int32& i) cil managed
// 代碼大小 6 (0x6)
} // end of method Program::F2
我們通過生成的中間語言看到,這兩個方法隻有一個差别就是在F2的參數中多了一個[out],方法體中是全部一樣的。其實對于CLR來說,這兩個關鍵字是沒有差別的,都是能以引用類型的方式來操作參數。
為什麼在C#中要區分out和ref呢?主要是因為out是輸入參數,隻希望它從方法内得到值傳回,而ref即要把參數帶到方法,也可以帶出參數,就是說這隻是C#編輯器的願望,是以在C#中是差別的,但在CLR在運得exe的中繼資料是不區另的(因為托管理程式是兩次編譯)。
下面通過另一個方法看看ref和out
static void F1(ref int i)
static void F1(int i)
上面的代碼放在一個類中是能通過編譯的,因為構成了重載
我們看以看一下普通方法的IL
.method private hidebysig static void F1(int32 i) cil managed
IL_0001: ldc.i4.s 100
IL_0003: starg.s i
最明顯的差别是參數普通方法是int32 i,而加ref,out的是int32& i,參數的不同使重載成為可以。但ref和out,如果參數類型個數相同的話剛形不成重載,因為它們是相同的,不充許出現相同方法(方法的簽名)。
本文轉自桂素偉51CTO部落格,原文連結:http://blog.51cto.com/axzxs/149957 ,如需轉載請自行聯系原作者