宣言と呼び出しの両方で「ref」キーワードを使用する必要があるのはなぜですか。
void foo(ref int i)
{
}
たとえば、上記の関数を考えてみましょう。refキーワードなしで呼び出す場合
foo(k);
エラーが発生します:
引数 '1' は 'ref' キーワードと共に渡す必要があります
メソッドの署名のみで指定するだけでは十分ではないのはなぜですか?
宣言と呼び出しの両方で「ref」キーワードを使用する必要があるのはなぜですか。
void foo(ref int i)
{
}
たとえば、上記の関数を考えてみましょう。refキーワードなしで呼び出す場合
foo(k);
エラーが発生します:
引数 '1' は 'ref' キーワードと共に渡す必要があります
メソッドの署名のみで指定するだけでは十分ではないのはなぜですか?
これはref
、パラメーターが参照によって渡される必要があることを示しているためです。C++のポインターのようなものです
例えば;
void CalFoo()
{
var i=10;
foo(ref i); //i=11
}
void foo(ref int i)
{
i++;
}
しかし
void CalFoo()
{
var i=10;
foo(i); //i=10
}
void foo(int i)
{
i++;
}
1 つのクラスでfoo(ref int)
との両方を使用できると思います。foo(int)
..を指定しない場合ref
、コンパイラはどの関数を呼び出すかをどのように判断するのでしょうか?
読みやすさ/理解のしやすさが向上します。メソッド呼び出しを見ると、ref 値が変更される可能性があることがわかります。
(前述のように、これはこの質問のだまされています。)
1 つには、メソッドのオーバーロードの一部として使用されます。
public void Foo(string x) { ... }
public void Foo(ref string x) { ... }
...
string x = "";
Foo(x); // Which should be used if you didn't have to specify ref?
1つの答えは、そのようなオーバーロードを禁止することかもしれません...しかし、C#が呼び出し側でドキュメントとしてこれを要求することは良いことだと思います:
ref
(またはout
)を使用すると、動作が大幅に変わります。C# 4 では for COM メソッドの暗黙的な使用が許可されていることに注意してください。これは、実際には動作しない (または少なくとも、それらはそれを利用しない)パラメータref
が非常に多いためです。このような場合、コンパイラは新しいローカル変数を導入して、呼び出し元の観点から引数が実際に値渡しされるようにします。ref
ref
ComMethod(x);
に変換します。
MyType tmp = x;
ComMethod (ref tmp);
これは、COM メソッドにとっては適切な妥協点ですが、通常のマネージ コードには当てはまらないことを嬉しく思います。
メソッドと呼び出し元は互いに「遠く」離れている可能性があるため (異なるアセンブリでは、メソッドを含むアセンブリのソースさえない場合があります)、out と ref を明示的に指定する必要があるため、意図が明確になります。つまり、技術的な必要性ではなく、ユーザーが何をしているのかを本当に理解できるようにするためのものです。
ほとんどref
の場合、メソッド シグネチャから推測できますが、メソッドの呼び出し後にコードの動作を完全に変更できるため、常に必須です。検討:
string hello = "world";
MyMethod(ref hello);
Console.WriteLine(hello);
キーワードがそこになかった場合ref
、コードは常に「世界」を出力すると予想しますが、実際には何でも出力できます。
また、その理由は (C# の他の多くの「機能」と同様に) プログラマーに、呼び出しようとしている関数が引数を使用していることを思い出させるためであると聞いたことがあります (またはどこかで読んだことがあります - おそらくそれは言語設計者とのインタビューでした)。参考までに。