まさるblog

越後在住子持ちプログラマー奮闘記 - Author:まさる(高野 将、TAKANO Sho)

目次

Blog 利用状況

ニュース

著書

2010/7発売


Web掲載記事

@IT

.NET開発を始めるVB6プログラマーが知るべき9のこと

CodeZine

実例で学ぶASP.NET Webフォーム業務アプリケーション開発のポイント

第1回 3層データバインドを正しく活用しよう(前編)

ブログパーツ


書庫

日記カテゴリ

コミュニティ

夢の競演みたび(アンコール)

前エントリ:夢の競演みたび

えムナウさんから

C#になったんであれば一言。
関数型が好きというコメントよりも。
ToList() の意味を聞くべきだったんじゃないかな?
loop なしの List => List にこだわったんだと思うが。
プログラム的には無駄。

こんなコメントいただきました。

まず、ToList()の意味ですが、これはIEnumerable<T>をループでぶん回してList<T>を作るってメソッドだと、私は認識してみます。

そして、Where()もループぶん回すので、都合2回ループ処理が行われます。このあたりが「プログラム的には無駄。」と指摘されたと思ってます。(合ってます?)

であれば、ループの回数は極力少なくするにはどうするか。Where()の戻り値はIEnumerable<T>なので、そのまま列挙して表示しちゃいましょう。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
  public class Cat
  {
    public string Name { get; set; }
    public string Type { get; set; }
  }

  class Program
  {
    static void Main(string[] args)
    {
      var nyans = new List<Cat>() {
        new Cat{Name="しゅうたん", Type="アメショ" },
        new Cat{Name="ろり", Type="アメショ" },
        new Cat{Name="みずきちゃん", Type="スコティ" },
        new Cat{Name="マグさん", Type="ほげ" }
      };

      var typedNyans = nyans.Where(x => x.Type != "ほげ");

      foreach(var nyan in typedNyans) {
        Console.WriteLine("{0}は{1}", nyan.Name, nyan.Type);
      }
    }
  }
}

25-29行目が変わった所です。まず、25行目でWhere()の結果をtypedNyansで受け取った後、27-29行目でforeachで処理します。前回使ったForEach()はList<T>のメソッドなので、今回は使えません。

#IEnumerable<T>にForEach()が欲しいと思うのは私だけ?

投稿日時 : 2010年5月27日 7:50

Feedback

# re: 夢の競演みたび(アンコール) 2010/05/27 10:25 aetos

さて、この新コードでは何回ループが回るでしょう?

# re: 夢の競演みたび(アンコール) 2010/05/27 11:31 まさる

「"ほげ"以外を列挙して表示する」のが目的なら、実は
foreach (var nyan in nyans)
{
 if (nyan.Type != "ほげ")
 {
  Console.WriteLine("{0}は{1}", nyan.Name, nyan.Type);
 }
}
が一番早いですけどね。

# re: 夢の競演みたび(アンコール) 2010/05/27 11:39 aetos

> #IEnumerable<T>にForEach()が欲しいと思うのは私だけ?

作る。
もしくは EnumerableEx.Run()
http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx

# re: 夢の競演みたび(アンコール) 2010/05/27 12:24 nonname

ToList()は遅延評価を防ぐために静的な情報にするのが目的では?
そういう意味でLoopを使わないのなら必要ないと読み取りました。

# 
Ito Blog
&raquo; Blog Archive

&raquo; IEnumerable???ForEach????????????????????? 2010/05/27 14:34 Pingback/TrackBack


Ito Blog
&raquo; Blog Archive

&raquo; IEnumerable???ForEach?????????????????????

# re: 夢の競演みたび(アンコール) 2010/05/27 14:43 渋木宏明(ひどり)

>都合2回ループ処理が行われます。このあたりが「プログラム的には無駄。」と指摘されたと思ってます。(合ってます?)

いいえ。

Where() が内部で独自にループを回すことはないです。

内部的には yield return で実装されているはずなので、Where() によって返された IEnumerable を foreach などで列挙する時、はじめてループは回ります。(遅延実行)

ただし、Where() が返した IEnumerable を foreach などで列挙すると、毎回 Where() の条件式が評価されるので、それが無駄になる場合はあり得ます。

>ToList()は遅延評価を防ぐために静的な情報にするのが目的では?

その方向が妥当です。

ただし、フィルタして作成したコレクションに項目を追加する予定がないなら、ToArray() でもいいと思います。

てか、「追加する予定がない」「追加してほしくない」ことを強調したい時、僕は ToArray() を使います。


>もしくは EnumerableEx.Run()

正解。

ちなみに、勝手に応用板を作成してみました。
http://hidori.spaces.live.com/blog/cns!F11BB9FD8E1BC5F9!2493.entry

# にゃんこ夢の共演まつり会場・勝手口 2010/05/27 21:06 すいません、VB4しかやってないんです、VBAはやったけど(ぼそ)

にゃんこ夢の共演まつり会場・勝手口

# 夢のあと 2010/05/27 22:26 まさるblog

夢のあと

タイトル  
名前  
Url
コメント