Quantcast
Channel: C#タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9364

【C#】IEnumerableの遅延評価でプロパティが書き換わらない

$
0
0

プロパティの値を変更したけど変わらない・・・

職場においてC#を利用して自社サービスを実装しているのですが、
IEnumerableではまったことをちょっとまとめておきたいと思います。

下記は起こった事象を簡単にしたものとなります。下記の例は、IEnumerableに入ったユーザ情報の名前が大文字になることを期待したものとなります。

// このようなクラスを読み込んでいます//class User {//    public string Name { get; set; }//}IEnumerable<User>users=new[]{"kato","saito","kondo"}.Select(n=>{returnnewUser{Name=n};});foreach(Useruserinusers){// 大文字に変換したはずなのに・・・user.Name=user.Name.ToUpper();}foreach(Useruserinusers){Console.WriteLine(user.Name);}

出力結果

kato
saito
kondo

なぜか最初の値のままでした・・・

そうなんです。参照が違っておりました。
Enumerable.RepeatとかEnumerable.Selectとかが遅延評価のIEnumerableを返すので、foreachToListで評価された際に初期化されてしまいます。

修正パターン1

IEnumerable<User>users=new[]{"kato","saito","kondo"}.Select(n=>{returnnewUser{Name=n};}).ToList();foreach(Useruserinusers){// 大文字に変換user.Name=user.Name.ToUpper();}foreach(Useruserinusers){Console.WriteLine(user.Name);}

ToList()することで再度評価されても同じ参照が返るので無事、大文字にできました。

KATO
SAITO
KONDO

修正パターン2

修正パターン1だと、2ループしてしまうのは性能上問題があると思いますので、下記の方法を考えました。

IEnumerable<User>users=new[]{"kato","saito","kondo"}.Select(n=>{returnnewUser{Name=n};});users=users.Select(u=>{u.Name=u.Name.ToUpper();returnu;});foreach(Useruserinusers){Console.WriteLine(user.Name);}

初期化の後にSelect()に修正して、無事、

KATO
SAITO
KONDO

大文字に置換することができました!

実行環境

  • C# 7.3
  • Windows 10

Viewing all articles
Browse latest Browse all 9364

Latest Images

Trending Articles