引数の値を変更する

タグの編集
投稿者 BB  (社会人) 投稿日時 2010/6/30 19:52:47
>・引数の値を変更する
>キーワードByRefを使用すると、メソッドの中で引数の値を変更して呼び出し元に反映することができ
>る。

このByRefを使った簡単なサンプルを例示していただけないでしょうか?
上記の説明だけでは、どのようなときに使えば良いのかわかりかねます
よろしくお願いします
投稿者 (削除されました)  () 投稿日時 2010/6/30 22:09:39
(削除されました)
投稿者 無知厚顔  (社会人) 投稿日時 2010/6/30 22:12:38
何事も自分で試さない人は、進歩はおぼつかない。しかし、出血大サービスしましょう。
Private Sub Button1_Click(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles Button1.Click
   Dim a As Integer = 0
   Dim b As Integer = 0
   Call subA(a)
   Call subB(b)
   Label1.Text = "a=" & a & " b=" & b
End Sub

Private Sub subA(ByVal argA As Integer)
  argA = 1
End Sub

Private Sub subB(ByRef argA As Integer)
  argA = 2
End Sub

もし、お尋ねの主旨と違っていたら御免なさい。(赤っ恥)
投稿者 (削除されました)  () 投稿日時 2010/7/1 09:58:37
(削除されました)
投稿者 BB  (社会人) 投稿日時 2010/7/1 10:03:32
http://homepage1.nifty.com/rucio/main/dotnet/shokyu/standard11.htm
こちらの講座で学習しております。
事例7のサンプルで、もしByRefを必要とするコードを書かなければならないときは
どのような動作をさせたいときなのですか?
おかしな質問だとは思いますが、今ひとつByRefを咀嚼できないのでよろしく
お願いします。
投稿者 さなだ丸  (社会人) 投稿日時 2010/7/1 10:31:57
値渡し:ByVal・・・メソッドに対してそのものを渡す
参照渡し:ByRef・・・メソッドに対して参照を渡す

ということなんですが、

ByValというのは、相手に対して「リンゴ」を渡す。にたいして、
ByRefというのは、相手に対して「リンゴの入った器」を渡す。
ということになります。

メソッド側でもらったリンゴをどのように処理しても、ByValであれば、渡したリンゴがあります。
しかし、ByRefの場合、器にミカンを入れたりすれば、ミカンの入った器に変わってます。

どのようなときというと難しいですが、こういった違いを考慮して使い分けます。
実際には、「メモリへ、どのように格納されているからどっちの方がいい」とかもあるはずです。
投稿者   (社会人) 投稿日時 2010/7/1 11:14:39
一番簡単な例としては、戻り値を2つ取りたい時じゃないでしょうか。
私がコーディングする時は、関数の戻り値は、
関数の処理が成功したか失敗したかのTrue/Falseにすることが多いので、
関数内で求めた結果を返すときは、ByRefで取ってあげることが多いです。
(逆に、関数内で求めた結果を関数の戻り値にして、引数で成功失敗を返すこともあります)

C言語のポインタの概念を理解していると、わかりやすいのですけれどね。
投稿者 ?-?  (その他) 投稿日時 2010/7/1 11:43:47
> 一番簡単な例としては、戻り値を2つ取りたい時じゃないでしょうか。

言いたいことはわかるのですが、「戻り値」という言葉自体の意味がきちんとあるので、ここでは、
「渡した引数の内容そのものを変更したい場合」というほうがいいのではないでしょうか?
一つしか引数渡していないで、その引数の値を結果変えたいこともあるでしょうし。
Functionの戻り値は成功・不成功(そしてそのエラーの番号)としたい場合もあるでしょうしね。
投稿者 るきお  (社会人) 投稿日時 2010/7/1 13:32:05
>事例7のサンプルで、もしByRefを必要とするコードを書かなければならないときは
>どのような動作をさせたいときなのですか?
ByRefは「手段」に過ぎないので、結果としての機能にByRefを使わないとできないことはありません。
なので、「ByRefを必要とするコードを書かなければならないとき」はちょっと想像できません。

また、ByRefは使用しないことを多くの人が推奨しており、ByRefが効果的に使われている事例を調べること自体が難しいかもしれません。

>上記の説明だけでは、どのようなときに使えば良いのかわかりかねます
以上のような理由で、「使えばよい」ときというものも特にないと思っています。

それでも一応、ByRefが使用されるのは既にあがっているような理由が多いです。
1.メソッドから複数の情報を返したい場合
2.メソッド内で引数を変更したい場合

1は戻り値をクラスや構造体にすることで解決でき、特にVB2010から使用できるTupleクラスを使うと楽ができます。…が、ByRefを使う場合の多くはこの事例のように感じます。

2は引数を交換するメソッドの例が有名です。
    
Public Sub Test()
    Dim X As Integer = 1
    Dim Y As Integer = 2

    Swap(X, Y)

    MsgBox ("X=" & X & ", Y=" & Y)

End Sub

Public Sub Swap(ByRef value1 As IntegerByRef value2 As Integer)

    Dim temp As Integer 

    temp = value1
    value1 = value2
    value2 = temp

End Sub


でも、このようなことをしたいという需要がそれほど多くないのでレアケースかなと思います。


他のプログラマが書いたコードを読めるようになるためにByRefの機能は抑えておいた方がいいですが、自分で書くプログラムではByRefは使わない方が良いと思います。
投稿者 (削除されました)  () 投稿日時 2010/7/1 13:56:30
(削除されました)
投稿者 BB  (社会人) 投稿日時 2010/7/1 13:58:42
みなさん有り難うございます。

(6年くらい前の「楽しくわかるプログラミングの定石」という本のサンプル)
スロットマシンを作成
するプログラムでByRefが使われおり、その部分でつまずいておりました。

スロットマシンのコードは掲載することができませんが、
そこではスロットマシンのドラムを3つ使用するために表示するpictureBoxコントロールとドラムの位置を引数に取っています。 
 
  
投稿者 るしぇ  (社会人) 投稿日時 2010/7/1 14:15:44
ByRef の説明としては
>・引数の値を変更する
>キーワードByRefを使用すると、メソッドの中で引数の値を変更して呼び
>出し元に反映することができる。
で十分。そのままなので、どのようなときもない。反映が必要な時以外
考えられない。

>http://homepage1.nifty.com/rucio/main/dotnet/shokyu/standard11.htm
>こちらの講座で学習しております。
関係無さそう。ByRef は必要ない。

>(6年くらい前の「楽しくわかるプログラミングの定石」という本のサンプル)
>スロットマシンを作成
>するプログラムでByRefが使われおり、その部分でつまずいておりました。
「つまずく」では意味が分かりませんが、
>スロットマシンのドラムを3つ使用するために表示するpictureBoxコントロール
>とドラムの位置を引数に
ByVal でも全く同じ動きをしそう。
> Visual Basic 中学校 > 初級講座 > 第34回 値型と参照型
http://homepage1.nifty.com/rucio/main/dotnet/shokyu/standard34.htm
のような問題は起こるけど、それはまた別の話。
試してみれば?

結局、自分のレベルにあっていない知識が邪魔して、基本が分かってない感じ。
基礎知識は、そんな難しい話じゃない。ごくごく単純な機能の話。
投稿者 BB  (社会人) 投稿日時 2010/7/1 18:39:11
るきおさん、丁寧に説明していただき感謝します。
投稿者 傍観者  (社会人) 投稿日時 2010/7/2 12:14:18
いやぁ、ホントに解っているのかな?
昔仕事でよく、こう言われた、「よし、何が解ったか、説明してみろ!」
いや、単なる一人言ですから、気にしないで下さい。
投稿者 (--;  (高校生) 投稿日時 2010/7/2 12:26:12
傍観者さん

> いやぁ、ホントに解っているのかな?
> 昔仕事でよく、こう言われた、「よし、何が解ったか、説明してみろ!」
> いや、単なる一人言ですから、気にしないで下さい。 

たぶん、傍観者さんはこの流れで内容がわかった上で発言しているのだと思うので、傍観者さんが説明してみてくださいな。
ちなみに、質問した人がわかっているかどうかは私にはわかりません。
投稿者 honefai  (社会人) 投稿日時 2010/7/2 17:43:03
>また、ByRefは使用しないことを多くの人が推奨しており

推奨はしてないことは無いように思います。
言語を始めたばかりの方にとっては、ByValとByRefを混在させてメソッドなど定義しちゃうと
混乱するので、初心者の方には推奨しないかも?ということならば理解できます。

ひとつ注意点として。。
プリミティブ型なら問題ないのですが、例えばListなどを引数とする場合、
ByValであっても、参照渡しになります。
例として、以下の場合ListをByValで渡していますが、コンソールには3件と表示されます。

    Dim hoge As New List(Of String)
    hoge.Add("hoge")
    hoge.Add("fuga")
    MossaMossaAA(hoge)
    Console.WriteLine(hoge.Count)

    Private Sub MossaMossaAA(ByVal hoge As List(Of String))
        hoge.Add("piyo")
    End Sub
 
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2010/7/2 18:36:19
> 例えばListなどを引数とする場合、ByValであっても、参照渡しになります。
それは違います。
あくまでも「参照型を値渡し」しているだけであって、
「参照型を参照渡し」している事にはなりません。

提示された例で言えば、MossaMossaAA メソッド内で
 hoge = New List(Of String())
を実行した場合、呼び出し元の List は変更されません。引数が ByVal だからです。
(もしもこれが ByRef であれば、呼び出し元の List も変更されることになります)
投稿者 るしぇ  (社会人) 投稿日時 2010/7/2 18:47:44
> ちなみに、質問した人がわかっているかどうかは私にはわかりません。
今回の質問者のような受け答えをすると、相手には分かっていない
と判断されるでしょうね。
ボクも分かってないのでは?との印象を持ちました。

プログラムを仕事としていますが、顧客に対して業務内容の質問を
する事が度々あります。分野は様々、管理会計や物流・在庫管理
ならまだ一般的ですが、中小企業相手ならかなりマイナーな分野に
関わる事もあります。当然、最初は全く知識の無い状態からはじまる
ことが多いです。

だからといって、
> おかしな質問だとは思いますが、今ひとつByRefを咀嚼できないので
> よろしくお願いします。 
こんなセリフを出してしまうと、まず言われます。
『大丈夫ですか?』
質問の言葉だけでなく、受け答えの言葉も重要です。
なぜ相手にそのような印象を与えるのか、よくよく分析した方が
いいですよ。

> 推奨はしてないことは無いように思います。
まぁ、これは色々な基準があると思いますので一概には言えませんが、
コーディング規約レベルでガイドラインを決める場合もあります。
設計思想がかなり影響する内容です。
必ず正解とは言えませんが、多少、雰囲気がつかめそうな議論の
スレッドをあげておきます。
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=36332&forum=7

> プリミティブ型なら問題ないのですが、
値型と参照型の問題ですね。
>>スロットマシンのドラムを3つ使用するために表示するpictureBoxコントロール
>>とドラムの位置を引数に
>ByVal でも全く同じ動きをしそう。
>> Visual Basic 中学校 > 初級講座 > 第34回 値型と参照型
>http://homepage1.nifty.com/rucio/main/dotnet/shokyu/standard34.htm
このサイトでも解説している内容ですので、改めて確認してみてください。
「参照型を参照渡し」している事と「参照型を値渡し」している違いも
表になってます。
投稿者 (削除されました)  () 投稿日時 2010/7/2 19:11:01
(削除されました)
投稿者 まるしぇ  (社会人) 投稿日時 2010/7/2 19:16:50
るしぇ  の発言って上から目線じゃねぇ 
もう少し謙虚に語れよ
投稿者 るしぇ  (社会人) 投稿日時 2010/7/2 19:24:54
> るしぇ  の発言って上から目線じゃねぇ 
> もう少し謙虚に語れよ 
絶対いや:P
投稿者 KY  (社会人) 投稿日時 2010/7/2 19:45:57
>結局、自分のレベルにあっていない知識が邪魔して、基本が分かってない感じ

るしぇの仕事はサービス業だよな。
顧客に対してもこんなセリフを言うんだ
言葉遣いには気をつけろ
もっとも慇懃無礼にもな
投稿者 YuO  (社会人) 投稿日時 2010/7/2 19:51:49
>>また、ByRefは使用しないことを多くの人が推奨しており
>推奨はしてないことは無いように思います。

「多くの人」は知りませんが,少なくとも「Microsoft」は推奨していないです。
MSDN: パラメーターの引き渡し
http://msdn.microsoft.com/ja-jp/library/ms229053.aspx
> out パラメーターや参照パラメーターの使用は避けてください。
> 参照型を参照で渡さないでください。

outパラメータはC#でいうoutで,VBでは<Out> ByRefとなるものです。
参照パラメータはVBのByRefそのものです (C#ならref)。

このあたりは,FxCopの規則にもあったりします。
MSDN: CA1021: out パラメーターを使用しません
http://msdn.microsoft.com/ja-jp/library/ms182131.aspx
MSDN: CA1045: 型を参照によって渡しません
http://msdn.microsoft.com/ja-jp/library/ms182146.aspx

一応,例外としてのTryParseパターンというものも最初の文書にあったりしますが。
MSDN: 例外とパフォーマンス
http://msdn.microsoft.com/ja-jp/library/ms229009.aspx
投稿者 (--;  (高校生) 投稿日時 2010/7/2 22:04:48
> もう少し謙虚に語れよ 

> 言葉遣いには気をつけろ

自分がやってないことを他人に強要する典型的な例ですね。
そういうった発言は当人には決して届かずに流されるだけ。

> もっとも慇懃無礼にもな 

たぶん、誤字なんだろうけど、意味わかってる?
こういう使い方している人と会話していれば「出来れば日本語でしゃべってください」って言いたくなる気持ちわかってくれると思うのですけどね。
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2010/7/2 23:32:19
> を実行した場合、呼び出し元の List は変更されません。引数が ByVal だからです。

誤記:hoge = New List(Of String())
訂正:hoge = New List(Of String)()
投稿者 るしぇ  (社会人) 投稿日時 2010/7/3 00:12:47
> 自分がやってないことを他人に強要する典型的な例ですね。
自分で認められなくて惰性でやってるだけ。掲示板で回答者として
常連の人に相手にしてもらいたくて4年も前から粘着してる人なん
だよ。人生の目的が違うんでしょう。理解する必要もつっこみ入れる
必要もありませんので。ボクが相手したのはそろそろ事情を知らない
新規の人が増えてきたからだよ。
また放置に戻ります。
若いうちはこういう人間でも立ち直らせたいと思うでしょ?
まぁ、止めないけど、4年の実績に対抗できる実力で行かないと
徒労に終わるからね。続けるならその覚悟して頑張って^^;

> 顧客に対してもこんなセリフを言うんだ
自分が客の立場にいるつもりwwwwオレ様大好きだもんね。

>> もっとも慇懃無礼にもな 
>たぶん、誤字なんだろうけど、意味わかってる?
これも自分が言われたのよ。丁寧な言葉をつかってさえ内容
すかすかでしょ?自分が間違ってることを認めたくないために、
実は分かってるけどわざとやってるんだよ~という伏線なので
気にしなくていいです。お察し。
投稿者 るしぇ2  (社会人) 投稿日時 2010/7/3 03:51:31
> 自分がやってないことを他人に強要する典型的な例ですね。
自分で認められなくて惰性でやってるだけ。掲示板で回答者として
常連の人に相手にしてもらいたくて4年も前から粘着してる人なん
だよ。人生の目的が違うんでしょう。理解する必要もつっこみ入れる
必要もありませんので。ボクが相手したのはそろそろ事情を知らない
新規の人が増えてきたからだよ。
また放置に戻ります。
若いうちはこういう人間でも立ち直らせたいと思うでしょ?
まぁ、止めないけど、4年の実績に対抗できる実力で行かないと
徒労に終わるからね。続けるならその覚悟して頑張って^^;

> 顧客に対してもこんなセリフを言うんだ
自分が客の立場にいるつもりwwwwオレ様大好きだもんね。

>> もっとも慇懃無礼にもな 
>たぶん、誤字なんだろうけど、意味わかってる?
これも自分が言われたのよ。丁寧な言葉をつかってさえ内容
すかすかでしょ?自分が間違ってることを認めたくないために、
実は分かってるけどわざとやってるんだよ~という伏線なので
気にしなくていいです。お察し。

他人を冷笑するるしぇは、質問者と同じレベルの人間ってことで
いすね。みんなも了解したと思う。
自分も気づかないその毒舌がきっと貴殿を幸せに(?)してくれる
ことでしょう。
投稿者 無記名  (社会人) 投稿日時 2010/7/3 04:31:27

>自分で認められなくて惰性でやってるだけ。
どうしてそう決めつけるわけ?
>掲示板で回答者として常連の人に相手にしてもらいたくて4年も前から粘着してる人なん
>だよ。
本当にその人なのかわからないのでは?思いこみでものを言うのはいかがなもの?

>人生の目的が違うんでしょう。理解する必要もつっこみ入れる
>必要もありませんので。ボクが相手したのはそろそろ事情を知らない
>新規の人が増えてきたからだよ。
>また放置に戻ります。
>若いうちはこういう人間でも立ち直らせたいと思うでしょ?
>まぁ、止めないけど、4年の実績に対抗できる実力で行かないと
>徒労に終わるからね。続けるならその覚悟して頑張って^^;
なんか、すごく目線が高いんだよね
俺様は、おまえらとは人間が違うんだよ、と言ってるように聞こえるんだよね
本人はそのつもりではないんだと思うけどネ

るしぇ君は、まだ若いんだと思う。20代でしょ。きっと
仕事面ではきっとバリバリできるエリートなんだろう
自分でも自信を持っていると思う(過信かもしれないが、失礼(^^;)

でも肝心な心が育っていないのが残念です。
でも、これからいろいろな経験を積んで人間的にも成長してほしい。
自分をおとしめるような発言はしないほうが身のためですよ(^O^)

魔界の仮面弁士さんやるきおさんのように技術面だけでなく心も
大らかにね。

管理人さんへ、 おかしな発言は削除願います。
また、掲示板は登録制にしたほうがよろいしかと考えます
ご一考ください。


 
  
投稿者 投稿者  (社会人) 投稿日時 2010/7/3 07:28:43
不適切な発言は即刻削除されますようにお願いします。
登録制にすることに賛同します
投稿者 honefai  (社会人) 投稿日時 2010/7/3 10:26:55
>あくまでも「参照型を値渡し」しているだけであって、
>「参照型を参照渡し」している事にはなりません。

すいません、中途半端な書き方をしてしまいました、たしかにそのとおりです。
正確には、

×ByValであっても、参照渡しになります。
○ByValであっても、参照型の場合は参照型の値渡しになるので、
 渡って来た ByVal hoge As List(Of String) は、別メモリにListのリファレンスが格納されているが(値渡し)
 その参照元は渡ってくる元の Dim hoge As New List(Of String) と同じメモリを参照してるので、
 そのリストのアイテムなりを更新しても、元のリストまで更新されちゃいますよ。

です。
投稿者 がく  (社会人) 投稿日時 2010/7/5 10:45:29
> 他人を冷笑するるしぇは、質問者と同じレベルの人間ってことで
ごめん、どうしてもつっこみたくなったwww
なにげにひでぇwwww
心の中で質問者の方を見下してるし。

諭すように見えて棘ありまくりの自作自演テンプレも飽きたよ。
もう見るの6回目くらいかなぁ。
話しの流れ無視して登録制とか言い出すところまで一緒。
投稿者 老爺  (社会人) 投稿日時 2010/7/5 11:01:17
>ごめん、どうしてもつっこみたくなったwww
あやまるくらいなら発言は差し控えていただきたかった。

荒らしに対しては、あくまでスルーが基本であり、それが賢明な姿勢であると思う。
投稿者 (削除されました)  () 投稿日時 2010/7/5 12:48:10
(削除されました)
投稿者 がく  (社会人) 投稿日時 2010/7/5 12:50:57
> あやまるくらいなら発言は差し控えていただきたかった。
> 荒らしに対しては、あくまでスルーが基本であり、それが賢明な姿勢であると思う。
なぜ?いつの間に?共通認識で全部荒らし扱いになってます?
荒らしスルーできないから謝ったわけじゃないです。
投稿者 流れ者  (社会人) 投稿日時 2010/7/6 16:05:19
BBさん

なにか、変な流れになっていますが、BBさんには責任はありませんのでお気になさらずに。

ByValとByRefの使い方については、るきおさんやさなだ丸さんがおっしゃっている通りです。
使い分けは、数をこなしていく中で自分なりのルールができると思います。

ただ、るきおさんがおっしゃっているように、ByRefでないと成立しない状況は極めて稀だと私も思います。