ref 關鍵字通過引用(而非值)傳遞參數。 通過引用傳遞的效果是,對所調用方法中的參數進行的任何更改都反映在調用方法中。 例如,如果調用方傳遞本地變量表達式或數組元素訪問表達式,所調用方法會將對象替換為 ref 參數引用的對象,然后調用方的本地變量或數組元素將開始引用新對象。
說明:
不要混淆通過引用傳遞的概念與引用類型的概念。 這兩種概念是不同的。 無論方法參數是值類型還是引用類型,均可由 ref 修改。 當通過引用傳遞時,不會對值類型裝箱。
若要使用 ref 參數,方法定義和調用方法均必須顯式使用 ref 關鍵字,如下面的示例所示。
class RefExample
{
static void Method(ref int i)
{
// Rest the mouse pointer over i to verify that it is an int.
// The following statement would cause a compiler error if i
// were boxed as an object.
i = i + 44;
}
static void Main()
{
int val = 1;
Method(ref val);
Console.WriteLine(val);
// Output: 45
}
}
傳遞到 ref 形參的實參必須先經過初始化,然后才能傳遞。 這與 out 形參不同,在傳遞之前,不需要顯式初始化該形參的實參。 有關詳細信息,請參閱 out。
類的成員不能具有僅在 ref 和 out 方面不同的簽名。 如果類型的兩個成員之間的唯一區別在於其中一個具有 ref 參數,而另一個具有 out 參數,則會發生編譯錯誤。 例如,以下代碼將不會編譯。
class CS0663_Example
{
// Compiler error CS0663: "Cannot define overloaded
// methods that differ only on ref and out".
public void SampleMethod(out int i) { }
public void SampleMethod(ref int i) { }
}
但是,當一個方法具有 ref 或 out 參數,另一個方法具有值參數時,則可以完成重載,如下面的示例所示。
class RefOverloadExample
{
public void SampleMethod(int i) { }
public void SampleMethod(ref int i) { }
}
在其他要求簽名匹配的情況下(如隱藏或重寫),ref 和 out 是簽名的一部分,相互之間不匹配。
屬性不是變量。 它們是方法,不能傳遞到 ref 參數。
有關如何傳遞數組的信息,請參閱 使用 ref 和 out 傳遞數組(C# 編程指南)。
你不能將 ref 和 out 關鍵字用於以下幾種方法:
-
異步方法,通過使用 async 修飾符定義。
-
迭代器方法,包括 yield return 或 yield break 語句。
示例
前面的示例演示當通過引用傳遞值類型時會發生什么情況。 你還可以使用 ref 關鍵字傳遞引用類型。 通過引用傳遞引用類型可以使所調用方法將調用方法中的對象替換為引用參數所引用的對象。 對象的存儲位置按引用參數的值傳遞到方法。 如果更改參數存儲位置中的值(以指向新對象),你還可以將存儲位置更改為調用方所引用的位置。 下面的示例將引用類型的實例作為 ref 參數傳遞。 有關如何通過值和引用傳遞引用類型的詳細信息,請參閱 傳遞引用類型參數(C# 編程指南)。
class RefExample2
{
static void ChangeByReference(ref Product itemRef)
{
// The following line changes the address that is stored in
// parameter itemRef. Because itemRef is a ref parameter, the
// address that is stored in variable item in Main also is changed.
itemRef = new Product("Stapler", 99999);
// You can change the value of one of the properties of
// itemRef. The change happens to item in Main as well.
itemRef.ItemID = 12345;
}
static void Main()
{
// Declare an instance of Product and display its initial values.
Product item = new Product("Fasteners", 54321);
System.Console.WriteLine("Original values in Main. Name: {0}, ID: {1}\n",
item.ItemName, item.ItemID);
// Send item to ChangeByReference as a ref argument.
ChangeByReference(ref item);
System.Console.WriteLine("Back in Main. Name: {0}, ID: {1}\n",
item.ItemName, item.ItemID);
}
}
class Product
{
public Product(string name, int newID)
{
ItemName = name;
ItemID = newID;
}
public string ItemName { get; set; }
public int ItemID { get; set; }
}
// Output:
//Original values in Main. Name: Fasteners, ID: 54321
//Back in Main. Name: Stapler, ID: 12345