ref (C# リファレンス)
ref キーワードによって、値渡しではなく、参照渡しによって引数が渡されます。 参照渡しで渡すことにより、呼び出されたメソッドのパラメーターに対する変更が、呼び出し元のメソッドに反映されます。 たとえば、呼び出し元がローカル変数の式、または配列要素のアクセス式を渡し、呼び出されたメソッドが ref パラメーターが参照するオブジェクトを置き換える場合、呼び出し元のローカル変数または配列要素は新しいオブジェクトを参照します。
注意
参照渡しの概念と参照型の概念を混同しないでください。2 つの概念は同じではありません。メソッドのパラメーターは、値型か参照型かどうかに関係なく、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 だけが異なるシグネチャを持つことはできません。 1 つの型の 2 つのメンバー間の違いが、1 つには ref パラメーターがあり、もう 1 つには 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) { }
}
ただし、次の例に示すように、1 つのメソッドに ref または out パラメーターがあり、もう 1 つのメソッドに値パラメーターがある場合は、オーバーロードすることができます。
class RefOverloadExample
{
public void SampleMethod(int i) { }
public void SampleMethod(ref int i) { }
}
非表示やオーバーライドなど、シグネチャの一致が必要な他の状況では、ref と out はシグネチャの一部であり互いに一致しません。
プロパティは変数ではありません。 プロパティはメソッドであり、ref パラメーターに渡すことはできません。
配列を渡す方法については、「ref と out を使用した配列の引き渡し (C# プログラミング ガイド)」を参照してください。
次の種類のメソッドには、ref キーワードと out キーワードを使用することはできません。
async 修飾子を使用して定義した Async メソッド
yield return または yield break ステートメントを含む Iterator メソッド
使用例
前の例は、参照渡しで値型を渡したときの動作を示しています。 また、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
C# 言語仕様
詳細については、「C# 言語仕様」を参照してください。言語仕様は、C# の構文と使用法に関する信頼性のある情報源です。