質問: とても些細な質問なのですが、お答えしていただけるとありがたいです。 現在C#で書いているプログラムの中であるクラスのインスタンスのメンバにDictionaryで管理された多のモデルがあります。 1のモデルのインスタンス生成時に、そのインスタンス内で管理されている多のモデルのインスタンスのみで有効な共通の変数を保持して多のモデルで定義されているメソッド内で使用したいのですが、多のモデルのインスタンス変数にこの値を持たせるのは同じインスタンスのメンバ間では冗長で,staticにすると1のモデルのインスタンス間で個別に設定することができないので、関数の引数で渡すという方法でやるのが普通なのかなと思いました。 しかし,その多のモデルの関数の中でその設定値を用いた再帰を行う必要がある処理があり,これによって引き渡された値は不変であるにも関わらず再帰の中でメモリ保持されて多数作られてしまうのではないかという懸念があり,(この質問書いてるうちに解決策を思いついてしまったのですが)変数への参照を引数に渡せばいいのだと思いましたが、もっといい方法ありますでしょうか。 ご意見いただけると嬉しいです。よろしくお願いいたします。
回答: ご提示の状況を正しく解釈できてるか自信がないですが... だいたい以下のような感じという認識であってますか?? (ご質問の際は書きかけでもいいので具体的なソースを載せていただいたほうが話が早いと思います) ``` //1のモデルとなるクラス public class SingleModel { private readonly Dictionary multiDic; private readonly DateTime singleValue; public SingleModel() { //共通で使いたい変数値(仮にDateTimeとする) this.singleValue = DateTime.Now; //何らかのキーでDictionaryにして保持? this.multiDic = Enumerable.Range(1, 10) .ToDictionary(n => n, n => new MultiModel(n)); } public void CallDoSomething() { //多モデルオブジェクトすべてに対して関数呼び出し foreach (var multi in multiDic.Values) { multi.DoSomething(this.singleValue); } } } //多のモデルとなるクラス public class MultiModel { public MultiModel(int key) { } public void DoSomething(DateTime date) { //何かする ... //何らかの条件で再帰したりする //→再帰する度にDateTimeが生成されて無駄なのでは?? if (aCondition) DoSomething(date); } } ``` そのうえで、「変数への参照を引数に渡せばいいのだ」というのは、 上記の MultiModel.DoSomething メソッドを `public void DoSomething(ref DateTime date)` という形にするという意味でおっしゃってますか? もしそういう意味でしたら、個人的には賛成できません。 「多のモデルの関数の中でその設定値を用いた再帰を行う必要がある」というのは 多モデルクラスの内部実装の都合であって、 内部実装の都合によって外部からの呼び出しI/Fが決められてしまうのはスマートでないように思います。 特に「ref」は「引数で渡した値が変更されるかもしれないよ」ということを表現する目的で 使うのが一般的なので、コードの保守に際しては混乱の元にもなるかと思います。 どうしても参照で渡したければ、 * publicなDoSomethingメソッドで受け取った後に、そこからprivateな別メソッドを呼び出す際に 初めて引数をrefにする(そっちのprivateメソッドのほうで再帰する) または * その値のみをメンバに持つクラスを作成し、引数としてそのクラスのオブジェクトを渡す (structでなくclassならば参照渡しになる) ``` public class SingleValue //実際の用途にあわせて意味のある名前をつける { public DateTime Value { get; private set; } public SingleValue(DateTime value) { this.Value = value; } } ``` などの方法をとるほうが良いかなと思います。 ただ、多少再帰するからといって パフォーマンスに影響するほどではないのでは?という気もします。 「予測するな、計測せよ」と言われるとおり、パフォーマンスについては 実際に動かしてみて初めて分かる部分も大きいです。 まずは素直な形で作って、動かしてみて、問題があれば初めて最適化を考えるでも良いかもしれません。 もっというと、不変な値なのであれば素直にコンストラクタで渡してしまっても良いようにも思いました。 「多のモデルのインスタンス変数にこの値を持たせるのは同じインスタンスのメンバ間では冗長」 という気持ちも確かにわかりますが、readonlyなメンバにしておけば整合が取れなくなる心配はありませんし、 オブジェクトの状態が安定するメリットのほうが大きいのではないかと思いました。 いろいろ書きましたが、正直にいうとケースバイケースです。 具体的な状況がわからない以上、あくまで「基本的にはこう考えます」程度の意見だと思ってください。