どうして思ったのか
今日、GoogleでVB.NET 複数の値を返す メソッド
で検索した一番上のサイトがByRefを使った値の返し方をしていたからです。
Sub Main()
Dim a As Integer = 100
Dim b As Integer = 10
Dim tasizan As Integer = 0
Dim hikizan As Integer = 0
keisan(a, b, tasizan, hikizan)
Console.WriteLine("{0}, {1}", tasizan, hikizan)
End Sub
Sub keisan(data1 As Integer, data2 As Integer,
ByRef ans1 As Integer, ByRef ans2 As Integer)
ans1 = data1 + data2
ans2 = data1 - data2
End Sub
ByRefは最悪だと思う
個人的にByRef
は最悪だと思っています。というよりかはVB.NETのみならずメソッドの引数を参照渡しすることが最悪だと思います。もはやなぜ、ByRefが存在するのか分かりません。
理由
理由は3つあります。
- 知らぬ間に値が変わっている可能性がある
- 引数が大量になる
- メソッドの修正がしづらい
1. 知らぬ間に値が変わっている可能性がある
例で出したソースのkeisan
メソッドの呼出しを下記のように変更すると変数a
,b
の中身が変わってしまいます。
keisan(a, b, a, b)
これが個人的に一番の悪だと思っていて、コードは読みにくいし(同じ変数をなんで2つ渡してるんだ?ってなる)いつの間にか変数の中身が変わっていてコーディング中の脳内での変数の動きと実際の動きが変わってしまいます。
2. 引数が大量になる
現在のkeisan
メソッドは参照返しで足し算の結果と引き算の結果を返していますが、もし掛け算の結果とわり算の結果も返すようなメソッドの修正する場合は引数の数が6つに増えます。
Sub keisan(data1 As Integer, data2 As Integer,
ByRef ans1 As Integer, ByRef ans2 As Integer,
ByRef ans3 As Integer, ByRef ans4 As Integer)
ans1 = data1 + data2
ans2 = data1 - data2
ans3 = data1 * data2
ans4 = data1 / data2
End Sub
3. メソッドの修正がしづらい
例のkeisan
メソッドを修正して下記のようにすると割り算の結果が変更されていない状態でメソッドを抜ける実装になってしまいます。また、エラーも発生しませんし引数として渡された値が変わらないだけなので単体テストの際も不具合に気付かずにスルーしてしまう可能性があります。
Sub keisan(data1 As Integer, data2 As Integer,
ByRef ans1 As Integer, ByRef ans2 As Integer,
ByRef ans3 As Integer, ByRef ans4 As Integer)
ans1 = data1 + data2
ans2 = data1 - data2
ans3 = data1 * data2
'掛け算の結果が5以上ならメソッドを抜ける
If ans3 > 5 Then Exit Sub
ans4 = data1 / data2
End Sub
じゃあ、どうするのか
Tuple型を使って戻り値を返します。
Module Program
Sub Main()
Dim a As Integer = 100
Dim b As Integer = 10
Dim ret = keisan(a, b)
Console.WriteLine("{0}, {1}", ret.tasizan, ret.hikizan)
End Sub
Function keisan(data1 As Integer, data2 As Integer) As (tasizan As Integer, hikizan As Integer, kakezan As Integer, warizan As Integer)
Dim tasizan = data1 + data2
Dim hikizan = data1 - data2
Dim kakezan = data1 * data2
Dim warizan = data1 / data2
Return (tasizan, hikizan, kakezan, warizan)
End Function
End Module
理由が解決しているか確認する
ByRef
を使いたくない理由として下記の3点をあげていました。
- 知らぬ間に値が変わっている可能性がある
- 引数が大量になる
- メソッド内でソースを読むのが大変
これらが解決しているかを確認していきます。
1. 知らぬ間に値が変わっている可能性がある
keisan
メソッドの引数には値渡ししかないのでkeisan
メソッドを初めて使用する開発者でも知らぬ間に値が変わることはありません。
2. 引数が大量になる
もし、余りを返すようにメソッドを修正することになったとしても戻り値のTupleに追加するだけなので引数が増えることはありません。
Function keisan(data1 As Integer, data2 As Integer) As (tasizan As Integer, hikizan As Integer, kakezan As Integer, warizan As Integer, amari As Integer)
Dim tasizan = data1 + data2
Dim hikizan = data1 - data2
Dim kakezan = data1 * data2
Dim warizan = data1 / data2
Dim amari = data1 Mod data2
Return (tasizan, hikizan, kakezan, warizan, amari)
End Function
3. メソッドの修正がしづらい
戻り値を返さないとメソッドを抜けることができないので実装中に割り算の結果がないことに気が付きます。※Exit Functionを使えば抜けることができますが、それは開発者が無意識に実装している訳ではないので例外として下さい。
Function keisan(data1 As Integer, data2 As Integer) As (tasizan As Integer, hikizan As Integer, kakezan As Integer, warizan As Integer)
Dim tasizan = data1 + data2
Dim hikizan = data1 - data2
Dim kakezan = data1 * data2
If kakezan > 5 Then Return (tasizan, hikizan, kakezan, warizan)
Dim warizan = data1 / data2
Return (tasizan, hikizan, kakezan, warizan)
End Function
変数warizan
が参照できないのでコンパイルエラーになります。
おわりに
もし、ByRef
を有意義に使う方法を知っている方がいれば教えて頂きたいですm(_ _)m