200

値の型 ( 、 など) をパラメーターとして (キーワードなしで) 渡すと、その変数のコピーがメソッドに渡されることを理解してintstructますrefが、refキーワードを使用すると、その変数への参照が渡されます。新しいものではありません。

しかし、クラスのような参照型では、refキーワードがなくても、コピーではなく参照がメソッドに渡されます。refでは、参照型でのキーワードの使用は何ですか?


たとえば、次のとおりです。

var x = new Foo();

次の違いは何ですか?

void Bar(Foo y) {
    y.Name = "2";
}

void Bar(ref Foo y) {
    y.Name = "2";
}
4

10 に答える 10

177

fooを使用してポイントを変更できますy

Foo foo = new Foo("1");

void Bar(ref Foo y)
{
    y = new Foo("2");
}

Bar(ref foo);
// foo.Name == "2"
于 2009-06-07T11:13:28.473 に答える
34

指しているオブジェクトではなく、実際の参照を変更したい場合があります。

void Swap<T>(ref T x, ref T y) {
    T t = x;
    x = y;
    y = t;
}

var test = new[] { "0", "1" };
Swap(ref test[0], ref test[1]);
于 2009-06-07T11:13:20.173 に答える
22

Jon Skeet は、 C# でのパラメーターの受け渡しに関する素晴らしい記事を書きました。値、参照 ( ref)、および出力 ( out) によるパラメーターの受け渡しの正確な動作と使用法が明確に詳しく説明されています。

refパラメータに関連して、そのページからの重要な引用を次に示します。

参照パラメーターは、関数メンバーの呼び出しで使用される変数の値を渡しません。変数自体を使用します。関数メンバー宣言で変数の新しい格納場所を作成するのではなく、同じ格納場所が使用されるため、関数メンバーの変数の値と参照パラメーターの値は常に同じになります。参照パラメーターには、宣言と呼び出しの両方の一部として ref 修飾子が必要です。つまり、何かを参照渡しするときは常に明確です。

于 2009-06-07T11:25:31.617 に答える
10

ref キーワードを使用して参照型を渡す場合、参照を参照渡しすることで、呼び出すメソッドでパラメーターに新しい値を割り当てることができます。その変更は呼び出しスコープに反映されます。ref がなければ、参照は値によって渡され、これは起こりません。

C# にも ref によく似た 'out' キーワードがありますが、'ref' ではメソッドを呼び出す前に引数を初期化する必要があり、'out' では受信メソッドに値を代入する必要があります。

于 2009-06-07T11:17:31.273 に答える
5

渡された参照を変更できます。

void Bar()
{
    var y = new Foo();
    Baz(ref y);
}

void Baz(ref Foo y)
{
    y.Name = "2";

    // Overwrite the reference
    y = new Foo();
}

渡された参照を気にしない場合は、outを使用することもできます。

void Bar()
{
    var y = new Foo();
    Baz(out y);
}

void Baz(out Foo y)
{
    // Return a new reference
    y = new Foo();
}
于 2009-06-07T11:15:54.087 に答える
4

別のコードの束

class O
{
    public int prop = 0;
}

class Program
{
    static void Main(string[] args)
    {
        O o1 = new O();
        o1.prop = 1;

        O o2 = new O();
        o2.prop = 2;

        o1modifier(o1);
        o2modifier(ref o2);

        Console.WriteLine("1 : " + o1.prop.ToString());
        Console.WriteLine("2 : " + o2.prop.ToString());
        Console.ReadLine();
    }

    static void o1modifier(O o)
    {
        o = new O();
        o.prop = 3;
    }

    static void o2modifier(ref O o)
    {
        o = new O();
        o.prop = 4;
    }
}
于 2009-06-07T11:18:27.997 に答える
1

メソッドのパラメーターは常にコピーを渡しているようです。問題は何のコピーかです。コピーはオブジェクトのコピー コンストラクターによって行われます。C# ではすべての変数がオブジェクトであるため、すべての変数に当てはまると思います。変数 (オブジェクト) は、ある住所に住む人々のようなものです。それらの住所に住んでいる人を変更するか、電話帳でそれらの住所に住んでいる人への参照をさらに作成する (浅いコピーを作成する) ことができます。したがって、複数の識別子が同じアドレスを参照できます。参照型はより多くのスペースを必要とするため、スタック内の識別子に矢印で直接接続されている値型とは異なり、ヒープ内の別のアドレスの値を持っています (より大きなスペースが必要です)。このスペースはヒープから取得する必要があります。

値の型: 識別子 (値を含む = スタック値のアドレス)---->値の型の値

参照型: 識別子(値=スタック値のアドレスを含む)---->(値=ヒープ値のアドレスを含む)---->ヒープ値(ほとんどの場合、他の値へのアドレスを含む) Array[0]、Array[1]、Array[2] への方向

値を変更する唯一の方法は、矢印に従うことです。1 つの矢印が途中で失われたり変更されたりすると、値に到達できなくなります。

于 2014-03-07T10:10:14.897 に答える