質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

2回答

427閲覧

【C#】コール先関数で作成したインスタンスの有効性について

dt9672

総合スコア17

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2020/08/20 05:16

前提・実現したいこと

データのリストを作成するにあたり、データは呼び出し先の関数で作成し、呼び出し元でリストに追加する処理を実装します。
データは多種多様な変数を扱いたいのでクラスで定義します。
クラスには辞書型の変数を含み参照渡しになるため、呼び出し先で都度新規インスタンスを作成し、その新規インスタンスを返します。

作成したソースコード

下記のようなコードにて期待した通りの動作になりましたが、スコープについて理解が浅いためか不安が残っています。

C#

1public class Test1{ 2 public static void Main(){ 3 DataPlus dataPlus1 = new DataPlus(); 4 List <Data> mainData = new List <Data>(); 5 6 mainData.Add(dataPlus1.DataInit()); 7 mainData.Add(dataPlus1.DataInit()); 8 mainData.Add(dataPlus1.DataInit()); 9 10 mainData[1].a["key1"] = "valuex"; 11 mainData[2].a["key1"] = "valuey"; 12 13 System.Console.WriteLine(mainData[0].a["key1"]); // value1を期待 → ok 14 System.Console.WriteLine(mainData[1].a["key1"]); // valuexを期待 → ok 15 System.Console.WriteLine(mainData[2].a["key1"]); // valueyを期待 → ok 16 } 17} 18 19public class Data{ 20 public Dictionary <string, string> a = new Dictionary <string, string>(); 21} 22 23public class DataPlus{ 24 public Data DataInit(){ 25 Data subData = new Data(); 26 subData.a["key1"] = "value1"; 27 return subData; 28 } 29}

疑問点

Q1. dataPlus1.DataInit()の返り値は参照渡し、すなわち"Data subData = new Data();"で作成したインスタンスのポインタと理解していますが正しいでしょうか。

Q2. Q1が正しいとして、このコードが期待した動作になるのは正しいのでしょうか。それとも本来は誤ったコードであり、期待した通りの動作になっているのは偶然なのでしょうか。

<Q2補足>
dataPlus1.DataInit()内で作成されたインスタンスであるsubDataは「dataPlus1.DataInit()が終了したらいつでも破棄して良いメモリ領域」のような扱いになるものかと思っていました。
しかし実際は上記コードにてメモリ領域は保持され、期待した通りの値を返しています。
このため、結果から以下のように想像しています。

・C#のコンパイラが「subDataが指すメモリ領域はdataPlus1.DataInit()の終了後も他の関数によって使用されている」ことを認識し、当該メモリ領域を破棄しないようなコードを作成している?
あるいは
・C#の実行環境が同様に認識し、当該メモリ領域を破棄しないよう管理してくれている?

この想像が正しければ良いのですが、そうではなくunpredicableな動作がたまたま意図通りになっていることを危惧しております。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

Q1. dataPlus1.DataInit()の返り値は参照渡し、すなわち"Data subData = new Data();"で作成したインスタンスのポインタと理解していますが正しいでしょうか。

値型以外はオブジェクトの参照が返ってきます。C,C++のポインタとは違い、アドレスが移動する場合もあるので、参照とポインタは似ているが違うものと考えてください。
unsafe構文で真のポインタを扱う事も可能ではありますが、色々制約があります。

Q2. Q1が正しいとして、このコードが期待した動作になるのは正しいのでしょうか。それとも本来は誤ったコードであり、期待した通りの動作になっているのは偶然なのでしょうか。

流し見しただけですが、とりあえず正しいように見えます。

dataPlus1.DataInit()内で作成されたインスタンスであるsubDataは「dataPlus1.DataInit()が終了したらいつでも破棄して良いメモリ領域」のような扱いになるものかと思っていました。

オブジェクトがどこからも参照されなくなったら、GCがそのうち破棄します。(タイミングはGC次第です)

投稿2020/08/20 05:33

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dt9672

2020/08/20 06:25

ご説明ありがとうございます。参照の有無が管理されているとのことで安心いたしました。
guest

0

ベストアンサー

Q1、Q2ともに、それでよろしいかと。

厳密には、インスタンスのポインタ、ってわけではありませんが。

投稿2020/08/20 05:20

y_waiwai

総合スコア88042

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dt9672

2020/08/20 06:26

ご確認ありがとうございました。すぐにご回答いただき助かりましたのでベストアンサーとさせていただきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問