1. 程式人生 > >【C#】 ref out

【C#】 ref out

ref

通常我們向方法中傳遞的是值,方法獲得的是這些值的一個拷貝,然後使用這些拷貝,當方法執行完畢後,這些拷貝將被丟棄,而原來的值不會受到影響。 這種情況是通常的,當然還有另外一種情況,我們向方法傳遞引數的形式,引用(ref)和輸出(out)。

有時,我們需要改變原來變數中的值,這是我們可以向方法傳遞變數引用,而不是變數的值,引用是一個變數,他可以訪問原來變數的值,修改引用將修改原來變數的值。變數的值儲存在記憶體中,可以建立一個引用,他指向變數在記憶體中的位置,當引用被修改時,修改的是記憶體中的值,因此變數的值可以被修改,當我們呼叫一個含有引用引數的方法時,方法中的引數將指向被傳遞給方法的相應變數,因此,我們會明白為什麼當修改引數變數的修改也將導致原來變數的值被修改。

建立引數按引用傳遞的方法,需使用關鍵字ref,例:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 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側重輸出。

ref

通常我們向方法中傳遞的是值,方法獲得的是這些值的一個拷貝,然後使用這些拷貝,當方法執行完畢後,這些拷貝將被丟棄,而原來的值不會受到影響。 這種情況是通常的,當然還有另外一種情況,我們向方法傳遞引數的形式,引用(ref)和輸出(out)。

有時,我們需要改變原來變數中的值,這是我們可以向方法傳遞變數引用,而不是變數的值,引用是一個變數,他可以訪問原來變數的值,修改引用將修改原來變數的值。變數的值儲存在記憶體中,可以建立一個引用,他指向變數在記憶體中的位置,當引用被修改時,修改的是記憶體中的值,因此變數的值可以被修改,當我們呼叫一個含有引用引數的方法時,方法中的引數將指向被傳遞給方法的相應變數,因此,我們會明白為什麼當修改引數變數的修改也將導致原來變數的值被修改。

建立引數按引用傳遞的方法,需使用關鍵字ref,例:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 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側重輸出。