1. 程式人生 > >C# ref和out總結

C# ref和out總結

技術分享 pos 操作 arm 代碼 cnblogs for set href

C# 中ref 與 out 總結

  參數的傳遞一般分為兩種:一種是“值傳遞”即:傳遞實參的拷貝,既然是拷貝那麽在函數中對這個形參所作的任何動作都不會反映到原來的實參中。另外一種是“引用傳遞”即:傳遞實參的地址(形參和實參指向同一塊內存地址),那麽在函數中對形參所作的任何改變都要反映到原來的實參中。

  在C#中實現“引用傳遞”的兩種方式為:ref 和 out。當然這兩種方式也有他們的不同,下面將逐步講解他們的不同之處。

  1. 使用ref關鍵字進行“引用傳遞”時,傳入的實參必須先被初始化,這就像C和C++中的指針一樣,一定要先給它賦值(讓它指向一個指定的內存位置),要不然它不一定會指向內存的哪裏,這樣很危險,不允許。而使用out關鍵字進行“引用傳遞”時,傳入的實參不必先初始化。如下面的例子所示: 技術分享
    1using System;
    2using System.Collections.Generic;
    3using System.Linq;
    4using System.Text;
    5
    6namespace RefAndOut
    7{
    8 class RefAndOutTesting
    9 {
    10 static void Main(string[] args)
    11 {
    12 int x;
    13 int y;
    14 OutTest(out x, out y);
    15 Console.WriteLine(string.Format("x = {0}, y = {1}", x, y));
    16
    17 int a = 100;
    18 int b = 200;
    19 RefTest(ref a, ref b);
    20 Console.WriteLine(string.Format("a = {0}, y = {1}", a, b));
    21 }
    23 //out參數在使用前不必初始化
    24 public static void OutTest(out int first, out int second)
    25 {
    27 first = 1;
    28 second = 2;
    29 }
    30 //ref參數在使用前必須初始化
    31 public static void RefTest(ref int first, ref int second)
    32 {
    33 first = 1111;
    34 second = 2222;
    35 }
    36 }
    37} 技術分享

  2. 雖然使用out關鍵字進行“引用傳遞”時,傳入的實參不必先初始化,但是在函數中一定要先對參數進行初始化,之後再使用。因為:在使用out參數的時候,程序首先將out的實參(形參)置空,(因此實質上實參先初始化了對此函數也沒有用)然後再對參數進行相應的操作;由於置空了,所以在離開該函數之前必須完成參數的初始化(即使你不對參數做任何操作),要不然該參數的指針又不知道該指向何處了。假如變化一下上面的OutTest函數: 1 public static void OutTest(out int first, out int second)
    2 {
    3 first = second;
    4 //first = 1;
    5 //second = 2;
    6 } 便會提示你:Use of unassigned out parmeter ‘second‘。即使你先初始化實參再去調用也會出現同樣的錯誤(原因就是out先對參數進行清空操作) 技術分享
    1 using System;
    2 using System.Collections.Generic;
    3 using System.Linq;
    4 using System.Text;
    5
    6 namespace OutAndRef
    7 {
    8 class Program
    9 {
    10 static void Main(string[] args)
    11 {
    12 //out變量在使用之前不必進行顯示的賦值
    13 int x = 1111;
    14 int y = 2222;
    15 OutTest(out x, out y);
    16 Console.WriteLine("x = {0}, y = {1}", x, y);
    17 }
    18
    20 public static void OutTest(out int first, out int second)
    21 {
    22 //離開這個函數前,必須對first和second賦值,否則會報錯。
    23 first = second;
    24 //上面這行會報錯,因為使用了out後,first和second都清空了,需要重新賦值,即使調用函數前賦過值也不行
    25 first = 1;
    26 second = 2;
    27 }
    29 }
    31 }
    32 技術分享

  3. 因此上面的兩點可以總結為:ref有出有進,out有出沒進。
  4. 使用ref和out進行“引用傳遞”,在定義方法和調用方法時,都要在參數前加ref和out關鍵字,以滿足匹配。
  5. 由於屬性是方法,不是變量;而指針是變量。所以屬性都不可以作為ref和out參數傳遞。如果在上面的RefAndOutTesting類中聲明兩個屬性,傳遞給RefTest和OutTest方法中,則會出錯! 技術分享 1 using System;
    2 using System.Collections.Generic;
    3 using System.Linq;
    4 using System.Text;
    5
    6 namespace RefAndOut
    7 {
    8 class RefAndOutTesting
    9 {
    10 //屬性(是方法,不是變量)所以不可以作為ref和out參數
    11 public static int firstNumber
    12 {
    13 get;
    14 set;
    15 }
    16 public static int secondNumber
    17 {
    18 get;
    19 set;
    20 }
    21
    22 //字段可以作為ref和out參數
    23 public static int myNumber;
    24 public static int yourNumber;
    25
    26 static void Main(string[] args)
    27 {
    28 //正確
    29 OutTest(out myNumber, out yourNumber);
    30 Console.WriteLine( "myNumber = {0}, yourNumber = {1}", myNumber, yourNumber);
    31 RefTest(ref myNumber, ref yourNumber);
    32 Console.WriteLine( "myNumber = {0}, yourNumber = {1}", myNumber, yourNumber);
    33
    34 //錯誤
    35 OutTest(out firstNumber, out secondNumber);
    36 Console.WriteLine("firstNumber = {0}, secondNumber = {1}", firstNumber, secondNumber);
    37 RefTest(ref firstNumber, ref secondNumber);
    38 Console.WriteLine("firstNumber = {0}, secondNumber = {1}", firstNumber, secondNumber);
    45 }
    46 }
    47 }

C# ref和out總結