2010年1月24日日曜日

値渡しと参照渡しと矢切の渡し

脳ミソのザル化を止めたい


C# では、と語ろうとした場合、「えーっと、どうだったかな?www」と言いかねない自分がいることに気づいたので、ちょっとまとめておく。

基本値渡しで、値のコピー

次のコードの場合、「参照型」の「値渡し」ということになり、器「x」に入っている参照情報を、器「dest」にコピーするというイメージでいいだろう。
  1. using System;  
  2.   
  3. public class Foo  
  4. {  
  5.   private string message;  
  6.   
  7.   public Foo(string s)  
  8.   {  
  9.     message = s;  
  10.   }  
  11.   
  12.   public override string ToString()  
  13.   {  
  14.     return message;  
  15.   }  
  16. }  
  17.   
  18. public class ExecFoo  
  19. {  
  20.   public static void Main(string[] args)  
  21.   {  
  22.     Foo x = new Foo("foo");  
  23.     Console.WriteLine(x);  
  24.     ExecFoo.f(x, "bar");  
  25.     Console.WriteLine(x);  
  26.   }  
  27.   
  28.   public static void f(Foo dest, string message)  
  29.   {  
  30.     dest = new Foo(message);  
  31.   }  
  32. }  
  33. /* 
  34.  * Build: 
  35.  * 
  36.  *   gmcs foo.cs 
  37.  * 
  38.  * Run: 
  39.  * 
  40.  *   mono foo.exe 
  41.  * 
  42.  */  
$ mono foo.exe
foo
foo

器「dest」の参照情報が入れ代わっただけなので、器「x」に影響はない。

値渡しだけど

参照先は同じなので、
  1. using System;  
  2.   
  3. public class Foo  
  4. {  
  5.   private string message;  
  6.   
  7.   public Foo(string s)  
  8.   {  
  9.     message = s;  
  10.   }  
  11.       
  12.   public string Message  
  13.   {  
  14.     get { return message; }  
  15.     set { message = value; }  
  16.   }  
  17.   
  18.   public override string ToString()  
  19.   {  
  20.     return message;  
  21.   }  
  22. }  
  23.   
  24. public class ExecFoo  
  25. {  
  26.   public static void Main(string[] args)  
  27.   {  
  28.     Foo x = new Foo("foo");  
  29.     Console.WriteLine(x);  
  30.     ExecFoo.f(x, "bar");  
  31.     Console.WriteLine(x);  
  32.   }  
  33.   
  34.   public static void f(Foo dest, string message)  
  35.   {  
  36.     dest.Message = message;  
  37.   }  
  38. }  
$ mono foo.exe
foo
bar

参照渡し

「ref」キーワードをつけることで、「参照渡し」になる。この場合、値のコピーではなく、値の参照情報を渡す。つまり、器「x」そのものの在り処を渡すイメージでいいだろう。
  1. using System;  
  2.   
  3. public class Foo  
  4. {  
  5.   private string message;  
  6.   
  7.   public Foo(string s)  
  8.   {  
  9.     message = s;  
  10.   }  
  11.   
  12.   public override string ToString()  
  13.   {  
  14.     return message;  
  15.   }  
  16. }  
  17.   
  18. public class ExecFoo  
  19. {  
  20.   public static void Main(string[] args)  
  21.   {  
  22.     Foo x = new Foo("foo");  
  23.     Console.WriteLine(x);  
  24.     ExecFoo.f(ref x, "bar");  
  25.     Console.WriteLine(x);  
  26.   }  
  27.   
  28.   public static void f(ref Foo dest, string message)  
  29.   {  
  30.     dest = new Foo(message);  
  31.   }  
  32. }  
$ mono foo.exe
foo
bar

矢切の渡し

「矢切の渡し」については次を参照。

もっと学ぶ

次を参照。

0 件のコメント:

コメントを投稿