ref
通常我們向方法中傳遞的是值,方法獲得的是這些值的一個拷貝,然后使用這些拷貝,當方法運行完畢后,這些拷貝將被丟棄,而原來的值不會受到影響。 這種情況是通常的,當然還有另外一種情況,我們向方法傳遞參數的形式,引用(ref)和輸出(out)。
有時,我們需要改變原來變量中的值,這是我們可以向方法傳遞變量引用,而不是變量的值,引用是一個變量,他可以訪問原來變量的值,修改引用將修改原來變量的值。變量的值存儲在內存中,可以創建一個引用,他指向變量在內存中的位置,當引用被修改時,修改的是內存中的值,因此變量的值可以被修改,當我們調用一個含有引用參數的方法時,方法中的參數將指向被傳遞給方法的相應變量,因此,我們會明白為什么當修改參數變量的修改也將導致原來變量的值被修改。
創建參數按引用傳遞的方法,需使用關鍵字ref,例:
using System; class gump { public double Square(ref double x) { x = x * x; return x; } } class TestApp { public static void Main() { gump doit = new gump(); double a = 3; double b = 0; Console.WriteLine("Before a={0},b={1}",a,b); b = doit.Square(ref a); Console.WriteLine("After a={0},b={1}", a, b); Console.ReadLine(); } }
通過測試我們發現,變量a的值已經被修改為9 了。
out
通過制定返回類型,可以從方法返回一個值,有時候,需要返回多個值,雖然我們可以使用ref來完成,但是C#專門提供了一個屬性類型,關鍵字為out,介紹完后,我們將說明ref和out的區別。
using System; class gump { public void math_routines(double x, out double half, out double squared, out double cubed) //可以是:public void math_rotines(//ref double x,out double half,out double squared,out double cubed) //但是,不可以這樣:public void math_routines(out double x,out double half,out double squared,out double cubed) //對本例子來說,因為輸出的值要靠X賦值,所以X不能再為輸出值 { half = x / 2; squared = x * x; cubed = x * x * x; } } class TestApp { public static void Main() { gump doit = new gump(); double x1 = 600; double cubed1 = 0; double squared1 = 0; double half1 = 0; Console.WriteLine("Before method->x1={0}", x1); Console.WriteLine("Before method->half1={0}",half1); Console.WriteLine("Before method->squared1={0}",squared1); Console.WriteLine("Before method->cubed1={0}",cubed1); doit.math_routines(x1, out half1, out squared1, out cubed1); Console.WriteLine("After method->x1={0}", x1); Console.WriteLine("After method->half1={0}", half1); Console.WriteLine("After method->squared1={0}", squared1); Console.WriteLine("After method->cubed1={0}", cubed1); Console.ReadLine(); } }
通過使用out關鍵字,我們改變了三個變量的值,也就是說out是從方法中傳出值
我們發現,ref和out似乎可以實現相同的功能,因為都可以改變傳遞到方法中的變量的值,但是二者本質的區別就是,ref是傳入值,out是傳出值,在含有out關鍵之的方法中,變量 必須有方法參數中不含out(可以是ref)的變量賦值或者由全局(即方法可以使用的該方法外部變量)變量賦值,out的宗旨是保證每一個傳出變量都必須被賦值
在傳入變量的時候,out關鍵字的變量可以不被初始化,但是沒有out 關鍵字的值要被賦值。而ref參數在傳遞給方法是,就已經被賦值了,所以ref側重修改,out側重輸出。