3

ご挨拶、

値渡しと参照渡しの違いがわかります。しかし、参照(配列など)をrefで渡し、配列を値で渡すことは、私には理解できないようです。どうすれば参照ごとに参照を渡すことができますか?

     int[] myArray = {1,2,3};
     PassByVal(myArray);
     PassByRef(ref myArray);

     PassByVal(int[] array)
     {    array = new int[] {7,8,9};   // will not work }

     PassByRef(ref int[] array)
     {    array = new int[] {10,11,12}; }  // will work
4

4 に答える 4

9

参照によって参照を渡す場合、渡された変数を新しいオブジェクトへのポイントにすることができます。参照を値で渡す場合でも、オブジェクトの状態を変更できますが、変数が別のオブジェクトを指すようにすることはできません。

例:

void RefByRef(ref object x)
{
  x=new object(2);
}

void RefByValue(object x)
{
 x=new object(2);//Only changes a local variable and gets discarded once the function exits
}

void Test()
{
  object x1=1;
  object x1a=x1;
  RefByRef(ref x1);
  //x1 is now a boxed 2
  //x1a is still a boxed 1


  object x2=1;
  RefByValue(x2);
  //x2 is still a boxed 1
}
于 2010-11-11T22:39:08.310 に答える
2

あなたの質問に答えるために、最初にValueTypesを見てみましょう。ValueTypeはValueを保持します。つまり、値を保持する別のメモリ位置を指すのではなく、メモリ位置が値になります。

したがって、int i = 10;

int j = i;

ここで何が起こるかというと、iの値のコピーがjに割り当てられます。どちらも同じ値ですが、メモリ内の異なる場所にあります。つまり、値タイプを別の値タイプに割り当てるたびに、コピーが作成されます。

これをReferenceTypesと契約します。

オブジェクトo=10;

オブジェクトp=o;

oはReferenceTypeであるため、oは値10を保持するメモリ位置を指します(実際にはボックス化されていますが、単純にしておきます)。次の行で、pは同じメモリ位置を指しています。言い換えれば、参照タイには2つのことがあります。1.アドレスポインタ2.実際の「モノ」を保持する実際のメモリ位置(アドレスが指す)。

あなたがそれをはるかにうまくやれば、私たちは価値と参照による通過に進むことができます。

C#では、パラメーターは値で渡されます。したがって、valueTypeパラメーターを期待するメソッドにvalueTypeを渡す場合は、

int i = 10;
SomeMethod(i);
Console.WriteLine(i);

static void SomeMethod(int value)
{
  value = 20;
}

SomeMethodが呼び出されると、iの値のコピーがメソッドに送信されます。メソッドがパラメーターを操作する場合、元の変数iには影響しません。したがって、コンソールウィンドウに表示されるのは10です。

これを参照型と契約します。

  class Program
  {
    static void Main(string[] args)
    {
      Customer c = new Customer() { Name = "Mike" };
      SomeMethod(c);
      Console.WriteLine(c.Name);
    }

    static void SomeMethod(Customer customer)
    {
      customer.Name = "John";
    }
  }

  class Customer
  {
    public string Name { get; set; }
  }

cは参照型なので。そして、C#はパラメータを値で渡します。参照の「値」のコピーが渡されます。つまり、アドレスcが指している値が渡されます。このメソッドでは、アドレスが同じであるため(コピーですが、同じメモリ位置を指します)、メソッドはオブジェクトの状態を操作できます。したがって、コンソールウィンドウに表示されるのは、「マイク」ではなく「ジョン」です。

ただし、メソッドが別のインスタンスをパラメーター(この場合は「顧客」と呼ばれる)に割り当てようとする場合。その後、物事は変化します。

  class Program
  {
    static void Main(string[] args)
    {
      Customer c = new Customer() { Name = "Mike" };
      SomeMethod(c);
      Console.WriteLine(c.Name);
    }

    static void SomeMethod(Customer customer)
    {
      customer = new Customer();
      customer.Name = "John";
    }
  }

  class Customer
  {
    public string Name { get; set; }
  }

このメソッドでは、Customerの新しいインスタンスを作成し、それをパラメーターcustomerに割り当て、この新しいインスタンスの名前を「John」に設定していることに注意してください。コンソールウィンドウに表示されるのは「マイク」であり、ジョンではありません。

これは、元の変数(c)のコピーがメソッドに渡される前に作成されたためです。このメソッドでは、別のアドレスがあり、その新しいアドレスを操作して、元のインスタンスが変更されないようにします。わかる?

わかりました、それが理にかなっているなら。では、SomeMethodに、私たちがやろうとしたことを実際に実行できるようにしたいとしたらどうでしょうか。そうですね、パラメータを値で渡すことはできませんが、参照で渡す必要があります。変数cと2つの部分(それが指しているアドレスの値とアドレス自体)が渡されていることを意味します。これで、参照型を参照で渡すことになります。

  class Program
  {
    static void Main(string[] args)
    {
      Customer c = new Customer() { Name = "Mike" };
      SomeMethod(ref c);
      Console.WriteLine(c.Name);
    }

    static void SomeMethod(ref Customer customer)
    {
      customer = new Customer();
      customer.Name = "John";
    }
  }

  class Customer
  {
    public string Name { get; set; }
  }
于 2010-11-11T23:13:34.077 に答える
2

このリンクをチェックすることをお勧めします。これは非常に便利で、C# でのパラメーターの受け渡しに関する非常に単純な例が含まれています。

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

void Foo (ref StringBuilder x) {
    x = null;
}

...

StringBuilder y = new StringBuilder();
y.Append ("hello");
Foo (ref y);
Console.WriteLine (y==null); // will write TRUE

あなたの例では

int[] myArray = {1,2,3};
PassByVal(myArray);
PassByRef(ref myArray);

PassByVal(int[] array){
    // the function copy the value of the pointer in a new location of memory
    // the "copied" pointer still points to the array 123    

    // now you are modifying the object pointed by THE COPY of the pointer
    // the original pointer still points to array 123
    // the copy of the pointer will point to array 456
    array = new int[] {7,8,9}; 

} // will not work

PassByRef(ref int[] array){
   // here you are passing the pointer without creating a copy of it in a 
   // new location of memory

   // we have not a original pointer and a "copyed" pointer
   // we have only the original pointer and now whe point it to array 10,11,12
   array = new int[] {10,11,12}; 
}  // will work
于 2010-11-11T22:44:39.563 に答える
0

これは少しややこしいように思えるかもしれませんが、実際にはそれほどトリッキーではありません。参照型のインスタンスを変数に代入すると、その変数のは、オブジェクト自体ではなく、オブジェクトへの参照になると言えます。その変数を値で別のメソッドに渡すと、参照のコピーが渡されます。呼び出されたメソッドは、呼び出し元のコードと同じインスタンスを「認識」します。代わりに参照によって変数を渡すと、呼び出し元のメソッドは、呼び出し元のコードと同じ参照のコピーを見ることができます。

これらの動作の違いは、参照によって変数を渡す場合、呼び出されたメソッドが変数に別の参照を割り当てる可能性があり (同じ型の別のインスタンスを参照するようにする)、呼び出し元のコードがこの変更を確認することです。そのような割り当てを行わない限り、 を使用する必要はありませんref

于 2010-11-11T22:40:31.230 に答える