🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C#

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

Q&A

解決済

2回答

1500閲覧

Listの中身を呼び出した関数先で書き換えたいが、反映されていないようです。

m.trsk

総合スコア7

C#

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

0グッド

0クリップ

投稿2019/10/29 08:47

こんにちは。お世話になってます。

Listの中身をを書き換える関数を作成したのですが、戻ってきたときに書き換えられていないようで困っています。

確認済みのこと

・書き換えの関数内では正常に書き換えられているが、
戻ったときに元のままである。

実際に書いたコード

不要な部分(Listの中身の取得など)は省いています。

C#

1static void Main(string[] args) 2 { 3 List<List<string>> lines = new List<List<string>>(); 4 //////(中略) 5 lines.Foreach(x => {Console.WriteLine(x);}); 6 //自作関数の呼び出し 7 Kakikae(lines); 8 lines.Foreach(x => {Console.WriteLine(x);}); //関数呼び出し前後で内容の変化がない 9} 10 11internal static void Kakikae(List<List<string>> lines) 12{ 13 lines.Foreach(item => 14 { 15 //書き換え内容(略) 16 }); 17}

関数内では変更が生きているのに返ってきたと単に元通りになります。
Listを関数で書き換えるのには新しく複製したリストを使って書き換えたものを戻り値にするなどすれば良いのでしょうか。
調べていて参照渡しや値渡しというもののせいだろうなと思ったのですが、
理解力不足、経験不足でどういうことなのか、そしてこれを解決するにはどうすればよいかが分かりませんでした。

現在の参照渡しと値渡しに対する理解度は以下です。
・参照渡しはデータのいる場所を渡してくれるもの。その場所の中身がコピーされて渡される。
・値渡しは値をそのまま渡しているもの。
・参照渡しをするにはrefを修飾子に就ける必要がある。
・Listはもとから参照を渡すのでrefは不要。
・Listを値渡しすることはできるのか????
というレベルです。

解説とアドバイスをお願いします。

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

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

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

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

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

Zuishin

2019/10/29 08:54 編集

kakikake(ref lines) を試さないのはなぜですか? ref をつけていないので参照渡しになっていません。
ozwk

2019/10/29 10:19 編集

そもそも関数を使わずに同じことをmainに書いてもちゃんと書き換わりますか?
m.trsk

2019/10/29 09:15

refについては既に試してみて、結局やりたいこと(関数先での書き換えがそのまま反映される)ができていなかったので違うのかと勝手に合点してしまいました。 どこか間違えてrefできてなかったのかもしれません。もう一回してみます。 間違えたのかもしれないと思い、確かめたことの中に入れていませんでした。すみません。
m.trsk

2019/10/29 10:14

すみません。関数の分け方などについて知識がなくて、、、 書き換わるかどうかなどの理解が乏しいです。書き換わると思っていました。 もう少し自分で調べてみます。
guest

回答2

0

ベストアンサー

とりあえず下記コードで,Change(L);の前後で表示が変わります.

static void Change( List<List<string>> lines ) { lines.ForEach( item => { item.Clear(); } ); } // static void Main(string[] args) { var L = new List< List<string> >(); L.Add( new List<string>{ "Cat", "Nap" } ); L.Add( new List<string>{ "Hello", "Kitten", "Lover" } ); L.Add( new List<string>{ "Fish" } ); L.ForEach( x=>{ Console.WriteLine( x.Count.ToString() ); } ); Change( L ); Console.WriteLine(); L.ForEach( x=>{ Console.WriteLine( x.Count.ToString() ); } ); }

問題の原因は(略)としている部分にあるのではないでしょうか?
とりあえずの物でもよいので現象が再現する形のコード(と表示結果)を示すと良いかと思います.

投稿2019/10/29 09:11

fana

総合スコア11985

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

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

0

C#

1 2 lines.Foreach(item => 3 { 4 item[0] = null; 5 }); 6

C#

1 foreach(List<string> item in lines) 2 { 3 item[0] = null; 4 }

は同じforeachでも動きが違うということを確認不足でした。
ラムダ式で行けるなら、と処理が重くなるのを避けてforeachにしており、
違うものに値を代入している形になったために直接の書き換えができていなかったようです。
ちょうど(略)と自分で勝手に省いてしまったその個所が原因のようです。

質問の仕方なども大変参考になりました。質問尾の仕方が悪すぎて申し訳ないです…。
以降ちゃんと質問できるように気をつけます。
ありがとうございました!

投稿2019/10/29 10:29

m.trsk

総合スコア7

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

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

ozwk

2019/10/29 23:35

static void Change( List<List<string>> lines ) { foreach(var item in lines){ item[0] = null; } //lines.ForEach( item => { item[0]=null; } ); } // static void Main(string[] args) { var L = new List< List<string> >(); L.Add( new List<string>{ "Cat", "Nap" } ); L.Add( new List<string>{ "Hello", "Kitten", "Lover" } ); L.Add( new List<string>{ "Fish" } ); L.ForEach( x=>{ Console.WriteLine( x[0] == null ? "null" : x[0] ); } ); Change( L ); Console.WriteLine(); L.ForEach( x=>{ Console.WriteLine( x[0] == null ? "null" : x[0] ); } ); } foreachでもForEachメソッドでも書き換わりますよ。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問