質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

Q&A

解決済

4回答

8152閲覧

メソッドの戻り値、参照渡しの結果について

yougo0411

総合スコア12

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

0グッド

0クリップ

投稿2016/06/27 01:14

編集2016/06/27 01:19

VB.Netのメソッドの戻り値、参照渡しの結果について、2点質問がございます。
理解不足なのでご教授お願いできませんでしょうか。


DataSetは参照型で、Returnした時点で参照型の代入によって別メモリに変数「dsResult」と同じ値が作成され、
メソッドAが終了した際は、変数「dsResult」のメモリは解放されるが、ReturnしたDetaSetは残る(Disposeの影響なし)、
という認識であっていますでしょうか。
(そもそも変数「dsResult」のDisposeが大きな意味がない、というご指摘も受けそうですが。)


引数「dsTest」はNothingの場合はメソッドA内で生成して処理をしますが、
レビュー指摘で『(参照渡し)dsTestはメソッドA内で生成されるとメソッドAが持つメモリになるので遷移元で生成』
、と指摘を受けました。
引数「dsTest」は遷移元とメソッドA内では同じメモリを参照しているので、生成処理が遷移元でもメソッドAでも
遷移元の変数が生成される、という認識ですが間違っていますでしょうか。

Sub メイン()
Dim dsTest As DataSet = Nothing
'
'処理
'
Dim dsRet As DataSet = メソッドA(dsTest)
End Sub

Shared Function メソッドA(ByRef dsTest As DataSet) As DataSet
Try
Dim dsResult As New DataSet
If dsTest Is Nothing Then
dsTest = New DataSet
'処理
End If
'SQLによるデータ取得結果をdsResultにセット
Return dsResult
Finally
If dsResult IsNot Nothing Then
dsResult.Dispose()
End If
End Try
End Sub

以下、「メソッドの戻り値について」を参考に考えてみたのですが、
少し理解に自信がないのでよろしくお願いします。
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=32024&forum=7

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

勘違いをされておりますが、懇切丁寧に説明するのは長くなるし 苦手ですので
ほかの方にお任せして、ヒントだけ。

DataSetで .Tables.Add とかするだけだったら ByRefでも ByValでも同じ。
参照型なんだから。
ByRefと ByValで変わるのは 上のDataSetが参照型かどうかとは関係なく
そのDatasetの入った変数自体を変えるときで
ByValだと、その変数を = New Dataset(~ ってやっても 元には影響しない。

投稿2016/06/27 02:21

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yougo0411

2016/06/27 12:00

2.について有り難う御座います。 参照渡しであれば、遷移元も関数内でも同じメモリを参照するので生成場所は関係なく、引き継がれる、と理解しました。
退会済みユーザー

退会済みユーザー

2016/06/27 12:58

1は いろいろありすぎて面倒で誰も回答してないのだと思います。 少なくとも、disposeについては、DataSetを使い終わったらにしましょうね。 戻してつかうんでしょう? DataSetのdisposeの必要性だの、Datasetの保持してるリソースの問題は 検索してください。 関数内の変数 dsResult のメモリを解放するのは そのdisposeではないし、 それはやる必要はないです。
guest

0

普段C#使っててVB.NETはどうなっているのか確かめようと
とりあえず1.について実験できるコード書いてみました

VB

1public class compiler 2 shared function Main as integer 3 Dim ret as Hoge 4 ret = A() 5 Console.WriteLine (ret.AskIfDisposed()) ' ここがどうなるか? 6 return 0 7 End function 8 9 shared Function A() As Hoge 10 Dim h As Hoge 11 Try 12 h = new Hoge() 13 Return h 14 Finally 15 h.FakeDispose() 'ここをコメントアウトしてみたりすると 16 End Try 17 End Function 18 19end class 20 21class Hoge 22 private isDisposed as boolean = false 23 24 public sub FakeDispose 25 isDisposed = true 26 end sub 27 28 public function AskIfDisposed as String 29 if isDisposed 30 return "disposed" 31 else 32 return "not disposed" 33 end if 34 end function 35end class

呼び出し元に影響します。

続いて2.

VB

1public class compiler 2 shared function Main as integer 3' Here your code ! 4 Dim ret as Hoge = Nothing 5 B(ret) 'ここをコメントアウトしてみたりしなかったりすると 6 7 if ret IsNot Nothing 8 Console.WriteLine ("not null") 'ここが表示されるか? 9 End if 10 return 0 11 End function 12 13 Shared sub B(ByRef h as Hoge) 14 h = new Hoge() 15 End sub 16 17end class 18 19class Hoge 20end class

呼び出し元に影響します。

『(参照渡し)dsTestはメソッドA内で生成されるとメソッドAが持つメモリになるので遷移元で生成』

文脈がわからないですが、素直に受け取ると、「なに言ってんだこいつ」って感じです。


「参照渡し」と「参照型変数の値渡し」は
それなりにプログラム組める人でも混同していることがあるので
注意です。

投稿2016/06/27 01:59

編集2016/06/27 07:36
ozwk

総合スコア13521

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yougo0411

2016/06/27 11:46 編集

サンプルコードを有り難う御座います。明日確認させて頂きます。 確認前の質問で申し訳有りませんが、「1 」ケースがまだしっくり来ません。 遷移元に影響するならば、リターン後にdisposeされても同じメモリを参照するので、遷移元ではdisposeされた値が取得できそうでが、実際にはreturn値が保持されています。 参照型の値渡しなので、return時に値渡しされ、disposeされるのはreturnの元、つまりメモリは別、という認識で大丈夫でしょうか。
ozwk

2016/06/27 23:50 編集

1.の例はdisposedと表示されます。 ちゃんとdisposeされた値が取得できます。 「参照型の値渡し」というのはざっくり言うとアドレス自体の値をコピーするという意味です。 メインのdsRetもメソッドAのdsResultも同じアドレスを指しています。 Dispose()をメモリ解放かなんかと勘違いしてませんか?
guest

0

ベストアンサー

1.まずメモリの開放については、取り合えず.Netに任せて忘れてください。不要なものは自動できれいにしてくれます。
2.基本型の変数にはreturnで、値が代入されます。
3.参照型の変数には、参照先のアドレス(以下ポインタ)が入っています。
4.参照型の変数にはreturnで、ポインタが入ってきます。
5.参照型の変数にアクセスする際は、ポインタをもとにアドレスを計算します。

インスタンス化された際のアドレスがやり取りされているとイメージするとわかりやすいと思います。

参照型はメソッド内でも、returnのときでも、やり取りされるのはアドレスで、実際の値ではないです。
アドレスなので、どちらも同じ変数を見に行きますし、コピーはされません。

投稿2016/06/27 05:07

iwamoto_takaaki

総合スコア2883

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yougo0411

2016/06/27 12:36

ご回答有り難う御座います。 やはり「1」の謎が残りまし、上記を考えるとreturn値とreturnのセット値は同じアドレスである、気がします。 しかしそこは値渡しされている、という事なのでしょうか?
iwamoto_takaaki

2016/06/27 13:36

1についてはガベージコレクションという機能で、参照されなくなったオブジェクトを削除して、メモリを解放したりする機能を持っています。 この機能は、C++などでは手動で行われ、効率的なメモリ管理を行える反面、プログラマに手間を強いていました。このため、Javaや.Netやその他オブジェクト指向を取り入れた言語は、参照されなくなったオブジェクトを監視し削除を自動で行います。 かなり、複雑な機構なので渡しはうまく説明することができません。でも、現時点では、メモリ解放は自動でやっているだけ理解しておけば問題はないと思います。 アドレスの渡し方ですが、アドレス用の変数が呼び出し元と先両方にとられるのか片方にしか取られないのかは、コンパイラが最適化するかどうかの話なので基本的には考えなくても良いと思います。ただ、基本はアドレス用の変数が、呼び出し元と呼び出し先両方で用意され、return時にアドレスの値をコピーすると考えた方が良いと思います。 私の想像で基本的にはそうした方が良い理由が幾つかありますし、少なくともポインタを利用する言語ではそれぞれに変数を定義するのは通例になっています。
guest

0

dsTest はメソッド A を呼び出す前に呼び出し側が初期化しなくてはなりません。
メソッド A 内で作られたものは破棄され、呼び出し側には戻りません。

もちろん、戻り値として呼び出し側に戻したものは別です。

例えば、呼び出し元が Hoge1 を作成して変数 a1 にセットして A を呼び出し、A の中で Hoge2 を作成して引数と戻り値にセットしたとします。
呼び出し元は A の戻り値を変数 a2 に代入します。
この場合、a1 の値は Hoge1 であって、Hoge2 ではありません。

追記

実験してみました。
出力は
Hi
Hi
となります。
私の間違いです。いい加減なことを書いて申し訳ありませんでした。

VB

1Imports System 2Imports System.IO 3 4Public Class Caller 5 Public Shared Sub Main() 6 Dim Hoge1 As New Hoge 7 Dim Hoge2 As Hoge 8 9 Hoge1.Message = "Hello" 10 Hoge2 = A(Hoge1) 11 Console.WriteLine(Hoge1.Message) 12 Console.WriteLine(Hoge2.Message) 13 End Sub 14 15 Private Shared Function A(ByRef hoge As Hoge) As Hoge 16 Dim Result As New Hoge 17 18 Result.Message = "Hi" 19 hoge = Result 20 Return Result 21 End Function 22End Class 23 24Public Class Hoge 25 Public Message As String 26End Class

投稿2016/06/27 02:04

編集2016/06/27 03:11
Zuishin

総合スコア28660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ozwk

2016/06/27 02:37

引数がByRef付きなのですが。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問