C#で変数パラメータを使用して参照渡しする方法はありますか?
質問
パラメータの変数リストを変更する関数が必要ですが、それらはすべて値型(int、string)です。 paramsキーワードをrefキーワードまたはそれに近いもので動作させる方法はありますか?
public void funcParams(params object[] list)
{
/* Make something here to change 'a', 'b' and 'c' */
}
public void testParams()
{
int a = 1, b = 2, c = 3;
funcParams(a, b, c);
}
問題は、オブジェクトフィールドを変更するメソッドを作成して、自分の人生をもっと楽にしようとしていることです。私はCecilを使用していくつかの動的なコード生成を行っており、IL生成コードを書きすぎないようにしています。
簡単にするために、フィールドのリストを参照で渡したいので、それぞれのILを生成して変更するのではなく、それらを変更する関数に変更する必要があります。一部のパラメーターはNULL値を許可されており、コード生成が少し難しくなります。この場合、paramsの代わりにいくつかのオーバーロードメソッドを作成してもあまり役に立ちません。
解決
はい。可能です。
ただし、結果のコードは「安全ではない」です。検証不能になります。
要件に応じて、問題になる場合とそうでない場合があります。
いずれにせよ、コードは次のとおりです。
using System;
namespace unsafeTest
{
class MainClass
{
public static void Main(string[] args)
{
Console.WriteLine("Hello World!");
unsafe
{
int x = 0;
int y = 0;
int z = 0;
bar(&x, &y, &z);
Console.WriteLine(x);
Console.WriteLine(y);
Console.WriteLine(z);
}
}
unsafe static void bar(params int *[] pInts)
{
int i = 0;
foreach (var pInt in pInts)
{
*pInt = i++;
}
}
}
}
他のヒント
まあ、あなたはいくつかのオーバーロードを宣言することができます、すなわち
public void FuncParams(ref int a) {...}
public void FuncParams(ref int a, ref int b) {...}
etc
それ以外の場合、配列から読み戻す必要があります( params
は実際には「暗黙の配列」を意味するため):
object[] args = {1,2,3};
funcParams(args);
Console.WriteLine(args[0]); // updated
Console.WriteLine(args[1]); // updated
Console.WriteLine(args[2]); // updated
(もちろん、 int
のみを受け入れる場合は、全体で int []
を使用する方が良いでしょう)
いいえ、きちんとした構文では不可能です。その理由は、内部的に、ランタイムがメソッドを配列引数を取る単純なメソッドとして扱うためです。コンパイラーは、配列を作成し、指定された引数で配列を埋めるハウスキーピングを行います。引数は値型であるため、引数は配列にコピーされ、それらの変更は元の変数に影響しません。
それを達成する他の方法は、可変数の引数のための素晴らしい構文である params
の存在の目的を無効にします。