2010年1月24日日曜日

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

このエントリーをはてなブックマークに追加
脳ミソのザル化を止めたい


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

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

次のコードの場合、「参照型」の「値渡し」ということになり、器「x」に入っている参照情報を、器「dest」にコピーするというイメージでいいだろう。
using System;

public class Foo
{
  private string message;

  public Foo(string s)
  {
    message = s;
  }

  public override string ToString()
  {
    return message;
  }
}

public class ExecFoo
{
  public static void Main(string[] args)
  {
    Foo x = new Foo("foo");
    Console.WriteLine(x);
    ExecFoo.f(x, "bar");
    Console.WriteLine(x);
  }

  public static void f(Foo dest, string message)
  {
    dest = new Foo(message);
  }
}
/*
 * Build:
 *
 *   gmcs foo.cs
 *
 * Run:
 *
 *   mono foo.exe
 *
 */
$ mono foo.exe
foo
foo

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

値渡しだけど

参照先は同じなので、
using System;

public class Foo
{
  private string message;

  public Foo(string s)
  {
    message = s;
  }
    
  public string Message
  {
    get { return message; }
    set { message = value; }
  }

  public override string ToString()
  {
    return message;
  }
}

public class ExecFoo
{
  public static void Main(string[] args)
  {
    Foo x = new Foo("foo");
    Console.WriteLine(x);
    ExecFoo.f(x, "bar");
    Console.WriteLine(x);
  }

  public static void f(Foo dest, string message)
  {
    dest.Message = message;
  }
}
$ mono foo.exe
foo
bar

参照渡し

「ref」キーワードをつけることで、「参照渡し」になる。この場合、値のコピーではなく、値の参照情報を渡す。つまり、器「x」そのものの在り処を渡すイメージでいいだろう。
using System;

public class Foo
{
  private string message;

  public Foo(string s)
  {
    message = s;
  }

  public override string ToString()
  {
    return message;
  }
}

public class ExecFoo
{
  public static void Main(string[] args)
  {
    Foo x = new Foo("foo");
    Console.WriteLine(x);
    ExecFoo.f(ref x, "bar");
    Console.WriteLine(x);
  }

  public static void f(ref Foo dest, string message)
  {
    dest = new Foo(message);
  }
}
$ mono foo.exe
foo
bar

矢切の渡し

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

もっと学ぶ

次を参照。

0 件のコメント:

コメントを投稿