C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

VB.NetのDictionaryについて

[トピック内 5 記事 (1 - 5 表示)]  << 0 >>

■97702 / inTopicNo.1)  VB.NetのDictionaryについて
  
□投稿者/ ぴっぴ (1回)-(2021/07/01(Thu) 22:06:57)

分類:[.NET 全般] 

VB.NetのDictionaryについて質問です。

Dim dic As Dictionary(Of Integer, List(Of 自作クラス)) = New Dictionary(Of Integer, List(Of 自作クラス))
というようにDictionaryを作成しました。

このDictionaryには、自作クラスが格納されたListをAddして追加しているのですが
このDictionaryからの値の取得がうまくいかず困っています。

Dictionaryに要素を追加する際は以下のように書いています。
dic.Add(i, lsttData)
※iはFor文のループカウンタ、lsttDataは自作クラスが格納されたListです。

Dictionaryから値を取得する部分は以下のように書いています。
Dim lst As List(Of 自作クラス) = dic(i)
※iはFor文のループカウンタ

このように取得すると、Dictionary内のすべてのListの値が取得されてしまいます。
Keyと一致する値のみ取得したいのですが、どのに問題があるのかわかりません。

VB.Netのフレームワークは4.7.2です。
どなたか詳しい方、よろしくお願いします。

引用返信 編集キー/
■97704 / inTopicNo.2)  Re[1]: VB.NetのDictionaryについて
□投稿者/ Azulean (1194回)-(2021/07/01(Thu) 23:38:30)
2021/07/01(Thu) 23:42:16 編集(投稿者)

No97702 (ぴっぴ さん) に返信
> Dictionaryに要素を追加する際は以下のように書いています。
> dic.Add(i, lsttData)
> ※iはFor文のループカウンタ、lsttDataは自作クラスが格納されたListです。

lsttData は New しなおしていますか?
List (Of 自作クラス) の New が一度だけの場合、すべての i で同じ 1 つの List (Of 自作クラス) を設定しています。


dic.Add は lsttData をコピーする(そのときの状態を覚える)のではなく、「参照」を追加します。
たとえて言えば、「倉庫の住所」を追加しておき、「倉庫」に何が入っているかは覚えません。
1 つの「倉庫」をみんなが使うので、どの i であっても「すべてが入った倉庫」=List になります。


参照型について改めて勉強していただいた方が良いかもしれません。
https://dobon.net/vb/dotnet/beginner/valuereference.html
引用返信 編集キー/
■97706 / inTopicNo.3)  Re[1]: VB.NetのDictionaryについて
□投稿者/ 魔界の仮面弁士 (3145回)-(2021/07/02(Fri) 09:16:05)
No97702 (ぴっぴ さん) に返信
> Dim dic As Dictionary(Of Integer, List(Of 自作クラス)) = New Dictionary(Of Integer, List(Of 自作クラス))
> というようにDictionaryを作成しました。
> dic.Add(i, lsttData)

たとえば、Dictionary(Of Integer, ListBox) を想像してみてください。
 dic.Add(0, Me.ListBox1)
 dic.Add(1, Me.ListBox1)
とした場合、ListBox1 という同一のインスタンスが Key 0 と Key 1 で共有されます。

この状態で、
 dic(1).Items.Add("New Item")
とすれば、Me.ListBox1 に対する操作となるわけですから、
dic(1).Items だけでなく dic(0).Items の件数も増加しますよね。

同一の List(Of ) インスタンスを登録していた場合も、それと同じ事が起きます。


『空の List(Of )』を追加することが目的なら、
 dic.Add(i, New List(Of 自宅クラス)())
のように、新しいインスタンスを追加します。


『既存リストのコピー』を追加したい場合は、別インスタンスを生成するために、
 dic.Add(i, lsttData.ToList())
とすることはできます。こうすることによって、
dic(1).Add 操作を行っても、dic(0) の件数が変化しなくなります。

また今回の場合、List(Of 自作構造体) ではなく
List(Of 自作クラス) であるため、場合によっては、
List(Of ) の個々のメンバーに対しても複製が必要になる可能性があります。

たとえば List(Of FileStream) を管理していた場合、そのリストを複製するにあたり、
 「同一のファイルストリームへの参照」
 「同じファイルを共有アクセスで開いている別のストリーム」
 「別フォルダの同名ファイルを開いているストリーム」
 「同フォルダの別名ファイルを開いているストリーム」
など、どのような複製が必要とされるかは、ケースバイケースですよね。
引用返信 編集キー/
■97707 / inTopicNo.4)  Re[2]: VB.NetのDictionaryについて
□投稿者/ ぴっぴ (2回)-(2021/07/02(Fri) 09:21:26)
No97704 (Azulean さん) に返信
> 2021/07/01(Thu) 23:42:16 編集(投稿者)
>
> ■No97702 (ぴっぴ さん) に返信
>>Dictionaryに要素を追加する際は以下のように書いています。
>>dic.Add(i, lsttData)
>>※iはFor文のループカウンタ、lsttDataは自作クラスが格納されたListです。
>
> lsttData は New しなおしていますか?
> List (Of 自作クラス) の New が一度だけの場合、すべての i で同じ 1 つの List (Of 自作クラス) を設定しています。
>
>
> dic.Add は lsttData をコピーする(そのときの状態を覚える)のではなく、「参照」を追加します。
> たとえて言えば、「倉庫の住所」を追加しておき、「倉庫」に何が入っているかは覚えません。
> 1 つの「倉庫」をみんなが使うので、どの i であっても「すべてが入った倉庫」=List になります。
>
>
> 参照型について改めて勉強していただいた方が良いかもしれません。
> https://dobon.net/vb/dotnet/beginner/valuereference.html

おっしゃる通りでした。
わかりやすい例えありがとうございます。
参照型について勉強し直します。
ありがとうございました!

解決済み
引用返信 編集キー/
■97708 / inTopicNo.5)  Re[2]: VB.NetのDictionaryについて
□投稿者/ ぴっぴ (3回)-(2021/07/02(Fri) 09:26:45)
No97706 (魔界の仮面弁士 さん) に返信
> ■No97702 (ぴっぴ さん) に返信
>>Dim dic As Dictionary(Of Integer, List(Of 自作クラス)) = New Dictionary(Of Integer, List(Of 自作クラス))
>>というようにDictionaryを作成しました。
>>dic.Add(i, lsttData)
>
> たとえば、Dictionary(Of Integer, ListBox) を想像してみてください。
>  dic.Add(0, Me.ListBox1)
>  dic.Add(1, Me.ListBox1)
> とした場合、ListBox1 という同一のインスタンスが Key 0 と Key 1 で共有されます。
>
> この状態で、
>  dic(1).Items.Add("New Item")
> とすれば、Me.ListBox1 に対する操作となるわけですから、
> dic(1).Items だけでなく dic(0).Items の件数も増加しますよね。
>
> 同一の List(Of ) インスタンスを登録していた場合も、それと同じ事が起きます。
>
>
> 『空の List(Of )』を追加することが目的なら、
>  dic.Add(i, New List(Of 自宅クラス)())
> のように、新しいインスタンスを追加します。
>
>
> 『既存リストのコピー』を追加したい場合は、別インスタンスを生成するために、
>  dic.Add(i, lsttData.ToList())
> とすることはできます。こうすることによって、
> dic(1).Add 操作を行っても、dic(0) の件数が変化しなくなります。
>
> また今回の場合、List(Of 自作構造体) ではなく
> List(Of 自作クラス) であるため、場合によっては、
> List(Of ) の個々のメンバーに対しても複製が必要になる可能性があります。
>
> たとえば List(Of FileStream) を管理していた場合、そのリストを複製するにあたり、
>  「同一のファイルストリームへの参照」
>  「同じファイルを共有アクセスで開いている別のストリーム」
>  「別フォルダの同名ファイルを開いているストリーム」
>  「同フォルダの別名ファイルを開いているストリーム」
> など、どのような複製が必要とされるかは、ケースバイケースですよね。

大変分かりやすい解説ありがとうございます。
勉強になります。

解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ