いもづる オブジェクト指向

参照渡しは独立性を損なう

私はたくさんのことを考えることは苦手です。あれはこっちに、それはあっちに影響するなんてのがあるともう考えられない。。 だから、参照渡しは使いません。影響範囲は小さいに限ります。

参照渡しの簡単な例です。

(1)

 1|    private void MainProc1(){
 2|        int number = 0;
 3|        this.Method1(ref number);
 4|
 5|        Console.WriteLine(number);
 6|    }
 7|
 8|    private void Method1(ref int number){
 9|        number++;
10|    }

コンソールには、"1" が出力されます。
C#は参照渡しについて多少気配りがされていて、メソッドに引数を渡す際に ref キーワードを指定しないとビルドエラーとなります。 呼出し側にも ref と記述させるので、numberが参照渡しで渡されることが見てわかります。

しかし実際このような使い方は、numberという変数を MainProc1 と Method1 で共有することに他なりません。 number変数を通じて、2つのメソッドは繋がっています。

参照渡しの糸(イメージ)
参照渡しの糸(イメージ)

このような場合は返り値を使い、次のようにするべきです。

(2)

 1|    private void MainProc2(){
 2|        int number = 0;
 3|        Console.WriteLine(this.Method2(number));
 4|    }
 5|
 6|    private int Method2(int number){
 7|        return ++number;
 8|    }

返す値が1つだけだからじゃないか!と思われると思います。確かにその通り。。 もし、2つも3つも値を返さないといけないのであれば、そのようなデータクラスを作成し、 Method2内でインスタンスを生成&値を設定して、returnするのがよいでしょう。
しかし、オブジェクト指向でクラス設計を行うと、 実際多くのデータを返す必要がある場合それらはそのような「データの塊」として意味をなすもので、それらは自然とクラスになっていることが多いものです。 参照渡しを使用して値をいくつも返さないといけないような状況になっているということは、 参照渡しで回避もいいですが、正しいクラス設計がされているかどうかを疑ってみる必要もあります。

もう1つ、上の例ではintという値型を渡していました。参照型の場合はどうでしょうか?

(3)

 1|    private class Data
 2|    {
 3|        public int Number = 0;
 4|    }
 5|
 6|    private void MainProc3(){
 7|        Data data = new Data();
 8|        data.Number = 0;
 9|        this.Method3(ref data);
10|
11|        Console.WriteLine(data.Number);
12|    }
13|
14|    private void Method3(ref Data data){
15|        data = new Data();
16|        data.Number = 99;
17|    }
11|}

9行目で、クラスDataのインスタンスへの参照を参照渡ししています。(長・・)
コンソールの出力は、"99" です。 9行目と14行目のdataは同じ変数なので、15行目で生成されたインスタンスへの参照値がdataに格納され、結果 MainProc3 でこのインスタンスを参照することになります。

これが値渡しだと(ref がないと)どうなるか? コンソールの出力は "0" となります。
14行目のdataの値は9行目のdataのコピーなので、Method3内でdataに何を入れられても呼び出し元の変数dataは何の影響も受けません。

このように、渡されるデータが参照値の場合は、いってみればオブジェクトをすりかえることができるかどうかです。 別のメソッドに行ったらオブジェクトがすりかえられる。。わざわざそんなめんどうでわかりにく設計をするでしょうか?しないですね。 やるならreturnで返して、呼出し側での代入でしょう。。

となると参照渡しの出番はあまりなさそうです。.NETは1.0の頃から開発していますが、参照渡しを使ったことは1度もありません。 参照渡しは、.NETが開発者への開発時の縛りを緩めにしていることの表れだと思います。 使う必要もないし、使ったらメソッド同士が結びついてしまう。

それなら、はじめから参照渡しは使わずに、メソッドの独立性を保ちましょう。

 

webmaster@e-ioo.net