一般的なプログラミング言語では、メソッドに引数を渡す際、大きく分けて値渡しと参照渡しの2種類があります。もちろんC#でも参照渡しを行うことができるのですが、これが3種類存在します。それが
- refキーワード
- outキーワード
- inキーワード (C#7.2より利用可能)
です。
それぞれの違いを確認してみましょう。
refキーワード
refキーワードは、他のプログラミング言語でも見られる一般的な参照渡しです。メソッドに与えるパラメータを、メソッド内で利用することを目的としています。そのため、引数に与えるパラメータには必ず値がセットされている必要があります。もし値が不明な場合は、次に紹介するoutキーワードの利用を検討すれば良いでしょう。
https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/ref
refキーワードを利用するときは、メソッドの宣言の際、引数にrefキーワードを付けます。またそのメソッドを利用するときもrefキーワードを付けます。利用時の注意点は、メソッドを呼び出す前にパラメータに値をセットしなければいけないということです。値をセットしなければ、エラーになります。
using System;
namespace GB
{
class Program
{
static void Main(string[] args)
{
int original = 1; // 値をセットしなければいけない
Sample(ref original);
Console.WriteLine(original);
}
static private void Sample(ref int value)
{
Console.WriteLine(value);
value = 2;
}
}
}
outキーワード
outキーワードは、メソッド内でセットされる値を、その後の処理で利用することを目的としています。例えば、int型やDatetime型などのTryParseメソッドでも利用されています。
https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/out-parameter-modifier
outキーワードを利用するときは、メソッドの宣言の際、引数にoutキーワードを付けます。またそのメソッドを利用するときもoutキーワードを付けます。利用時の注意点は、メソッド内でパラメータに値をセットしなければいけないということです。値をセットしなければ、エラーになります。
using System;
namespace GB
{
class Program
{
static void Main(string[] args)
{
int original;
Sample(out original);
Console.WriteLine(original);
}
static private void Sample(out int value)
{
value = 2; // 値をセットする必要がある
Console.WriteLine(value);
}
}
}
inキーワード
inキーワードは、C#7.2から利用できます。一言で言うならば、読み取り専用の参照渡しです。これまで引数に渡した値がメソッド内で変更されないためには、値渡しを利用していました。しかし値渡しは変数をコピーするため、巨大な配列などはコピーに時間がかかるデメリットもありました。このinキーワードは、処理の早い参照渡しでありながら読み取り専用であるため、パフォーマンス向上が期待できます。
https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/in-parameter-modifier
inキーワードを利用するときは、メソッドの宣言の際、引数にinキーワードを付けます。利用時の注意点は、inキーワードは読み取り専用を意味するため、メソッド内でパラメータに値をセットしてはいけません。値をセットしようとすると、エラーになります。
using System;
namespace GB
{
class Program
{
static void Main(string[] args)
{
int original = 1;
Sample(original);
Console.WriteLine(original);
}
static private void Sample(in int value)
{
Console.WriteLine(value);
// value = 2; // 値をセットするとエラーになる
}
}
}
まとめ
C#には、 3種類の参照渡しがあることを紹介しました。それぞれ明確に使い所が分かれていました。最終的にビルドされたバイナリでは全て同じ参照渡しとなりますが、コーディングレベルで分けられていると、処理の間違いが減るのでプログラマーにとっては嬉しいですね。