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

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

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

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

Q&A

解決済

5回答

3811閲覧

C# List<List<string>>のデータ入力と出力について

quiz3

総合スコア25

C#

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

0グッド

0クリップ

投稿2017/06/19 07:11

###前提・実現したいこと
C#を使ってList<List<string>>型に格納したデータを
Listboxに表示させるコードを作っています。

###発生している問題・エラーメッセージ

List型のデータを3件入れているつもりなのですが、
3件目のデータが3回表示されます。

###該当のソースコード

public Form1() { InitializeComponent(); // Listの使い方 //リストにデータを入力する List<List<String>> lt = new List<List<String>>(); List<string> ll = new List<string>(); //List型のデータをList型に入れる <--- これが上書きされている感じ? ll.Add("sub1"); ll.Add("sub2"); ll.Add("sub3"); lt.Add(ll); ll.Clear(); ll.Add("sub11"); ll.Add("sub12"); ll.Add("sub13"); lt.Add(ll); ll.Clear(); ll.Add("sub21"); ll.Add("sub22"); ll.Add("sub23"); lt.Add(ll); //Listboxに表示する int i = 0; foreach (List<string> l in lt) { if (i == 0) { foreach (string str in l) { listBox1.Items.Add(str); } } i++; } }

###試したこと

###補足情報(言語/FW/ツール等のバージョンなど)
VC2017 community, C#

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

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

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

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

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

guest

回答5

0

ベストアンサー

こんにちは。
原因は単純にたったひとつのListを使いまわしているからなんですが、
以下のように並べ替えてみるとその意味がわかると思います。

csharp

1ll.Add("sub1"); 2ll.Add("sub2"); 3ll.Add("sub3"); // ll = [ "sub1", "sub2", "sub3" ] 4 5ll.Clear(); // ll = [] 6ll.Add("sub11"); 7ll.Add("sub12"); 8ll.Add("sub13"); 9 10ll.Clear(); 11ll.Add("sub21"); 12ll.Add("sub22"); 13ll.Add("sub23"); // ll = [ "sub21", "sub22", "sub23" ] 14 15lt.Add(ll); 16lt.Add(ll); 17lt.Add(ll); // lt = [ ll, ll, ll ]

投稿2017/06/19 07:43

tamoto

総合スコア4103

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

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

quiz3

2017/06/19 12:52

ありがとうございます。 上記の例だとわかります。 普通のC言語だとA構造体にデータ入力後、それをB領域[0]に格納、 またA構造体に別のデータを入力後、B領域[1]に格納、という風にできるので、 そのつもりでコーディングしました。 C#ではAの中身を別の領域に格納後しても、アドレス渡しのような形なのでしょうか?
tamoto

2017/06/19 14:23

その通りです。 C#で扱えるデータは値型と参照型に大きく分類でき、Listなどの参照型のオブジェクトは基本アドレス渡しの挙動になります。
quiz3

2017/06/21 10:06

なるほど。 勉強になりました。ありがとうございました。
guest

0

csharp

1 2 // Listの使い方 3 //リストにデータを入力する 4 List<List<String>> lt = new List<List<String>>(); 5 List<string> ll = new List<string>(); 6 7 //List型のデータをList型に入れる <--- これが上書きされている感じ? 8 ll.Add("sub1"); 9 ll.Add("sub2"); 10 ll.Add("sub3"); 11 lt.Add(ll); 12 13 14 //Clearでは無くインスタンスを作成 15 ll=new List<string>(); 16 ll.Add("sub11"); 17 ll.Add("sub12"); 18 ll.Add("sub13"); 19 lt.Add(ll); 20 21 22 ll=new List<string>(); 23 ll.Add("sub21"); 24 ll.Add("sub22"); 25 ll.Add("sub23"); 26 lt.Add(ll); 27 28 29

Clearでは無く、llのインスタンスを新規作成しないと、おっしゃるとおり上書きになります(同じ子要素のリストを参照しているため)

---以下追記

リストボックスへの追加の方法が間違っています。
指摘漏れでしたスイマセン。

csharp

1 2 int i = 0; 3 foreach (List<string> l in lt) 4 { 5 if (i == 0) 6 { 7 foreach (string str in l) 8 { 9 listBox1.Items.Add(str); 10 } 11 } 12 i++; 13 } 14

i==0のコンディションがあるため、
最初の"sub1"、"sub2"、"sub3"列挙しか起こりません。

ですから、

csharp

1 2 //Listboxに表示する 3 foreach (List<string> l in lt) 4 { 5 foreach (string str in l) 6 { 7 listBox1.Items.Add(str); 8 } 9 } 10

このようにしてみたらいかがでしょうか?

投稿2017/06/19 07:21

編集2017/06/20 06:26
Tokeiya3

総合スコア260

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

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

quiz3

2017/06/19 12:55

ありがとうございます。 2件目、3件目のAdd前に「ll=new List<string>();」すると、 1件目しかデータが格納されないので、この構文は使わないことにしました。 単純に「ll.clear」の代わりに「ll=new List<string>();」を使ったんですが、 使用方法をまちがっているのでしょうか?
quiz3

2017/06/21 10:05

すみません。「1件目しか~」は、私の勘違いでした。 希望通りの表示になりました。 ありがとうございました。
guest

0

ll.Clear();
したら、そりゃ消えるでしょ。
同じものを指しているのだから、消えますし、最後のしか残りません。

新しいListを作るたびにnewをしてください。

投稿2017/06/19 07:16

kiichi54321

総合スコア1984

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

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

quiz3

2017/06/19 07:27

ありがとうございます。 ちなみになぜll.Clear()はダメなんでしょうか? イメージ的にll.Clear()を入れないと以下のようになると思っていました。 -------------------------------------- sub1 sub2 sub3 sub1 sub2 sub3 sub11 sub12 sub13 sub1 sub2 sub3 sub11 sub12 sub13 sub21 sub22 sub23 ----------------- という風に、どんどんつながっていくと思っていました。 ご教授いただけると幸いです。
quiz3

2017/06/19 12:54

なるほど!newしたものは参照! ありがとうございます。
guest

0

値型と参照型の違いという基本的なことろは理解されているとして・・・

3件目のデータが3回表示されます。

質問者さんのコードでは、lt[0], lt[1], lt[2] は最初の new List<string>() で作った同一オブジェクトを指すことになるのは分かりますか?

その List<string> 型のオブジェクトを、最終的に Clear して "sub21", "sub22", "sub23" を Add することにより書き換えてます。

lt[0], lt[1], lt[2] は同じ List<string> 型のオブジェクトを指しているのですから、3 つとも中身は最終的に書き換えた "sub21", "sub22", "sub23" で同じになったということでしょう。

投稿2017/06/19 08:53

編集2017/06/19 09:00
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

quiz3

2017/06/21 10:07

ありがとうございます。 みなさまの回答を見て理解できました。 ありがとうございました。
guest

0

ll.Clear(); が犯人ですね
ll.Clear(); の行を
ll = new List<string>(); にしてみたら期待通りの結果になりませんか?

投稿2017/06/19 07:13

編集2017/06/19 07:16
HiroshiWatanabe

総合スコア2160

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

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

quiz3

2017/06/19 07:26

ありがとうございます。 ll = new List<string>(); にすると、1件目だけしかInsertされていないようで、 のこりの2件は入っていませんでした。 ll.Clear()を削除してみると3件表示できました。 ありがとうございました。 ちなみになぜll.Clear()はダメなんでしょうか? イメージ的にll.Clear()を入れないと以下のようになると思っていました。 -------------------------------------- sub1 sub2 sub3 sub1 sub2 sub3 sub11 sub12 sub13 sub1 sub2 sub3 sub11 sub12 sub13 sub21 sub22 sub23 ----------------- という風に、どんどんつながっていくと思っていました。 ご教授いただけると幸いです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問