- PR -

参照型におけるByRef ByValについて

投稿者投稿内容
にゃー
常連さん
会議室デビュー日: 2008/06/26
投稿数: 32
投稿日時: 2008-07-25 13:55
現在、VisualStudio2005 VBを用いているのですが、
参照型の場合の引数において、
ByRefを使うべきかByValを使うべきなのかがわかりません。

質問前に調べたところ、以下のような解説がありました。
http://www.microsoft.com/japan/msdn/net/vbnetref/vbnetref3-6.aspx
http://www.atmarkit.co.jp/fdotnet/vb6tonet/vb6tonet11/vb6tonet11_01.html


上記microsoftさんのサイトから引用します。
----------------------------------------------
1: Private Sub Button1_Click(ByVal sender As System.Object, ...
2: Dim X As Integer = 1000
3: Dim MyArr() As Integer = {700, 800, 900}
4: F2(X, MyArr)
5: End Sub
6:
7: Private Sub F2(ByVal A As Integer, ByVal Dat() As Integer)
8: MsgBox(A)
9: MsgBox(Dat(0))
10: End Sub

ここで7行目において、ByRefとした場合とByValにした場合でどのように
変わってくるのでしょうか?
ByRefは参照情報をコピーすると思っているのですが、
ByValにおいても参照情報をコピーすると解説されております。

一般的には、このような場合はByValとByRefどちらを使うべきなのでしょうか?
burton999
ぬし
会議室デビュー日: 2003/10/06
投稿数: 898
お住まい・勤務地: 東京
投稿日時: 2008-07-25 14:11
普通はByValでByRefを使うことはないでしょう。
ByRefの場合、オブジェクトそのものを変更することが可能です。

例えばClassAとそれを継承したClassBがあったとして
メソッド側でクラス参照そのものを書き換えることができます。
メソッドを使う側としては、かってにインスタンスを変えられたら怖いですよね?
これは極端な例ですがで、特に理由が無いかぎりByValを使うべきです。

コード:

Privete Sub Main()
Dim a As ClassA = New ClassA()
Test(a)
End Sub

Private Sub Test(ByRef obj As ClassA)
obj = New ClassB()
End Sub



[ メッセージ編集済み 編集者: burton999 編集日時 2008-07-25 14:12 ]
にゃー
常連さん
会議室デビュー日: 2008/06/26
投稿数: 32
投稿日時: 2008-07-25 15:35
わかりやすい返答ありがとうございます。
返答内容を参考に、継承したクラスを用いてテストしてみました。
参照型においても、ByValとByRefで動作が違いを確認することができました。

Cのポインタと、値渡し的な概念(VB6までのByValとByRef)でしか
理解していなかったので助かります。

>これは極端な例ですがで、
このように書いてあるように、例のケースというのは、
よほどのコーディング(もしくは設計)ミスでしか起きないのではないか?
とも思います。
(フェールセーフとなるため、基本はByValを使用するようにします)

では逆に、参照型の変数を引数とする場合でByRefを用いるケースというのは、
どのような場合が考えられるのでしょうか?
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2008-07-25 16:01
引用:

にゃーさんの書き込み (2008-07-25 15:35) より:

Cのポインタと、値渡し的な概念(VB6までのByValとByRef)でしか理解していなかったので助かります。


C のポインタというか参照ですね。 「値型」 と 「参照型」 それに加え 「値渡し」 と 「参照渡し」 の 4 通りがあるという理解があれば問題ないでしょう。

> ByRefは参照情報をコピーすると思っているのですが、

参照情報というか、'参照' ですが、これはむしろ 「しない」 という理解で良いですね。

引用:

では逆に、参照型の変数を引数とする場合でByRefを用いるケースというのは、どのような場合が考えられるのでしょうか?


ないと思います。 少なくとも私は実験以外で使用したことがありません。 値型なら BCL にも System.Double.Parse(String, <OutAttribute> Double) メソッドなどがありますが参照型のパターンは知らないですね。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
まどか
ぬし
会議室デビュー日: 2005/09/06
投稿数: 372
お住まい・勤務地: ますのすし管区
投稿日時: 2008-07-25 20:22
引用:

では逆に、参照型の変数を引数とする場合でByRefを用いるケースというのは、
どのような場合が考えられるのでしょうか?



無理やり挙げるなら、返す値が多くて引数にするしかなかったという場合でしょうか。
Sub Func1(ByVal p1 As Integer, ByRef obj As Class1) As enumResult
いわゆるもらうだけというパターンですかね。
と言いつつ、この場合も全項目を持つ型を返すようにするほうが多いかな?
まぁ実際にこの形が候補として挙がることすら無いと言ってよいでしょう。

参照型ではありませんがイメージ的には、Int32.TryParseメソッドを見てみるとよいでしょう。
#↑かぶってやんの。。。

[ メッセージ編集済み 編集者: まどか 編集日時 2008-07-25 20:25 ]
くみちょ
会議室デビュー日: 2007/12/27
投稿数: 3
投稿日時: 2008-07-26 14:55
引用:

まどかさんの書き込み (2008-07-25 20:22) より:
>無理やり挙げるなら、返す値が多くて引数にするしかなかったという場合でしょうか。



この場合もByValでいいと思うのですが・・・
コード:

    Sub main()

        Dim cls1 As New class1
        Func1(1, cls1)
        MsgBox(cls1.item1.ToString) '66がかえってくる

    End Sub

    Class class1
        Public item1 As Integer
        Public item2 As Integer
        Public item3 As Integer
        Public item4 As Integer

    End Class

    Sub Func1(ByVal p1 As Integer, ByVal obj As class1)
        obj.item1 = 66
        obj.item2 = 77
        obj.item3 = 88
        obj.item4 = 99
    End Sub



まどか
ぬし
会議室デビュー日: 2005/09/06
投稿数: 372
お住まい・勤務地: ますのすし管区
投稿日時: 2008-07-26 22:27
引用:

この場合もByValでいいと思うのですが・・・
コード:
    Sub Func1(ByVal p1 As Integer, ByVal obj As class1)
        obj.item1 = 66





メンバの更新ではなくインスタンスを返す場合です。

コード:
    Dim obj As Class1
    Func1(1, obj)

    Sub Func1(ByVal p1 As Integer, ByRef obj As class1)
        obj = New Class1



テッテ
ベテラン
会議室デビュー日: 2008/03/16
投稿数: 91
投稿日時: 2008-07-26 23:35
Dictionary<TKey, TValue> クラスの TryGetValue はありますね。

スキルアップ/キャリアアップ(JOB@IT)