ref (C# リファレンス)
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のみが異なる定義を含めることはできません。コンパイラ エラーは、型の2個のメンバーの違いがそれらのに 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) { }
}
ただし、オーバーロードは、次の例に示すように、1種類のメソッドに 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を返します。 または 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
C# 言語仕様
詳細については、「C# 言語仕様」を参照してください。言語仕様は、C# の構文と使用法に関する信頼性のある情報源です。