C# で参照によってオブジェクトを渡す

Muhammad Maisam Abbas 2024年2月16日
  1. C# で変数を値で関数に渡す
  2. C# で変数を関数に参照で渡す
  3. C# の関数への参照によるオブジェクトの受け渡し
C# で参照によってオブジェクトを渡す

このチュートリアルでは、C# でオブジェクトを関数に渡す方法について説明します。

C# で変数を値で関数に渡す

C# では、すべての値型変数がデフォルトで値によって渡されます。変数を値で関数に渡し、その変数を関数で変更するとします。その場合、関数の引数で渡される変数の値には影響しません。ここで発生するのは、渡された変数の個別のコピーがメモリに作成され、すべての操作がその特定のコピーに対して実行されることです。次のコード例は、C# で値型変数を値で渡す方法を示しています。

using System;

namespace pass_object_by_reference {
  class Program {
    static void method1(string value) {
      value = "something";
      Console.WriteLine("New value = {0}", value);
    }

    static void Main(string[] args) {
      string valueType = "Nothing";
      method1(valueType);
      Console.WriteLine("Original Value = {0}", valueType);
    }
  }
}

出力:

New value = something
Original Value = Nothing

上記のコードでは、文字列変数 valueType を値で method1() 関数に渡しました。この関数は、渡された変数に新しい値を割り当てます。valueType 変数を値ごとに method1() 関数に渡すと、同じ値を持つ変数の 2つの異なるコピーがメモリに作成されます。次に、変数の 2 番目のコピーが something 値に変更されます。この 2 番目のコピーには、method1() 関数内でのみアクセスできます。この 2 番目の値を変更しても、元の変数 valueType は変更されません。

C# で変数を関数に参照で渡す

C# で ref キーワードを使用して参照することにより、値型変数を渡すこともできます。ref キーワードは、値が参照によって渡される関数に渡されることを指定します。このアプローチでは、メモリ内に変数のコピーが 1つだけ存在し、変数の値を指す関数に別のポインタが渡されます。次のコード例は、C# で ref キーワードを使用して参照によって値型変数を渡す方法を示しています。

using System;

namespace pass_object_by_reference {
  class Program {
    static void method1(ref string value) {
      value = "something";
      Console.WriteLine("New value = {0}", value);
    }

    static void Main(string[] args) {
      string valueType = "Nothing";
      method1(ref valueType);
      Console.WriteLine("Original Value = {0}", valueType);
    }
  }
}

出力:

New value = something
Original Value = something

上記のコードでは、C# で ref キーワードを指定して method1() 関数を参照することにより、値型変数 valueType を渡しました。method1() 関数は、引数として valueType 変数への参照を取り、valueType 変数の値を something に変更します。今回は、元の値が変更されます。

C# の関数への参照によるオブジェクトの受け渡し

デフォルトでは、クラスインスタンス、構造体インスタンスなどのすべての参照型変数は、C# の関数に参照によって渡されます。ここで起こることは、元のオブジェクトがパラメーターとして関数に渡されることは決してないということです。オブジェクトへの新しい参照は、関数への引数として値によって渡されます。したがって、同じメモリ位置を指すポインタのコピーが 2つあることになります。そのポインタの値を変更すると、元のオブジェクトの値も変更されます。次のコード例は、C# の関数を参照してオブジェクトを渡す方法を示しています。

using System;

namespace pass_object_by_reference {
  public class Sample {
    public string s { get; set; }
  }
  class Program {
    static void dosomething(Sample obj) {
      obj.s = "something";
    }
    static void Main(string[] args) {
      Sample sam = new Sample();
      sam.s = "Nothing";
      dosomething(sam);
      Console.WriteLine(sam.s);
    }
  }
}

出力:

something

上記のコードでは、sam オブジェクト内の s プロパティを変更する dosomething() 関数を参照して、オブジェクト sam を渡しました。元の sam オブジェクトの値を変更し、sam.s プロパティに something を割り当てます。これは参照によってオブジェクトを渡すデフォルトの方法ですが、このアプローチには 1つの例外があります。渡されたオブジェクトを new キーワードとクラスコンストラクタで初期化すると、オブジェクトの個別のコピーがメモリ内に作成されます。そのオブジェクトの値を変更しても、パラメーターとして渡された元のオブジェクトは変更されません。次のコード例は、このオブジェクトが値によって C# の関数に渡されるシナリオを示しています。

using System;

namespace pass_object_by_reference {
  public class Sample {
    public string s { get; set; }
  }
  class Program {
    static void dosomething(Sample obj) {
      Console.WriteLine("Initial passed value = {0}", obj.s);
      obj = new Sample();
      obj.s = "something";
      Console.WriteLine("New value = {0}", obj.s);
    }
    static void Main(string[] args) {
      Sample sam = new Sample();
      sam.s = "Nothing";
      dosomething(sam);
      Console.WriteLine("Original Value = {0}", sam.s);
    }
  }
}

出力:

Initial passed value = Nothing
New value = something
Original Value = Nothing

上記のコードでは、オブジェクト sam を C# の dosomething() 関数に値で渡しました。dosomething() 関数は引数を取り、その初期値を出力し、値を変更し、変更された値を出力します。この新しい値は新しいメモリ位置に割り当てられ、元のオブジェクト sam からはアクセスできません。

Muhammad Maisam Abbas avatar Muhammad Maisam Abbas avatar

Maisam is a highly skilled and motivated Data Scientist. He has over 4 years of experience with Python programming language. He loves solving complex problems and sharing his results on the internet.

LinkedIn

関連記事 - Csharp Class