2

私は簡単なプログラムを書きました、これはそれがどのように見えるか、いくつかの詳細は隠されています:

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

namespace routeaccounts
{
    class Program
    {
        static void Main(string[] args)
        {
            //Draw lines from source file
            var lines = File.ReadAllLines("accounts.txt").Select(p => p.Split('\t'));
            //Convert lines into accounts
            var accounts = lines.Select(p => new Account(p[0], p[1], p[2], p[3]));
            //Submit accounts to router
            var results = accounts.Select(p => RouteAccount(p));
            //Write results list to target file
            WriteResults("results.txt", results);
        }

        private static void WriteResults(string filename, IEnumerable<Result> results)
        {
            ... disk write call ...
        }

        private static Result RouteAccount(Account account)
        {
            ... service call ...
        }
    }
}

私の質問はこれです-明らかに、データコンテキストから選択するとき、実行は延期されます。お気づきの方もいらっしゃると思いますが、「Main」関数の最初のステートメントで、File.ReadAllLines( "accounts.txt")からクエリを実行しています。これは悪い選択ですか?最終結果を列挙すると、このステートメントは繰り返し表示されますか?

問題があることがわかっている場合は、単純に.ToArray()を実行するか、結果を事前に取得できますが、舞台裏で何が起こっているのかを知りたいと思っています。

4

3 に答える 3

4

.NET 4.0で使用するFile.ReadLinesと、ファイルの読み取りも怠惰になります。現在のように、ファイルの読み取りは延期されず、File.ReadAllLines戻ったときにファイル全体をメモリに読み取ります。これは1回だけ発生します。

于 2010-12-01T20:31:18.827 に答える
3

ファイルを繰り返し読み取ることはありません。実行のその部分は延期されないためです。配列を返し、次にを呼び出すとシーケンスが返されます...投影は延期されますが、ファイルの読み取りは延期されません。その配列は、それを参照するすべてのものが(直接的または間接的に)ガベージコレクションの対象になるまでメモリに残ります...ファイルを再読み取りする必要はありません。Select

一方、またはとにかく類似したものを使用して結果を読みたい場合があります。そうすれば、結果を書き始める前にToList()エラーを見つけることができるからです。副作用のあるコードの実行を開始する前に、必要なデータがすべて揃っていることを確認することをお勧めします(私が想像していることです)。明らかに、一度にメモリに必要なデータ量の点では効率が悪くなります...それはあなたが自分で検討しなければならないバランスです。WriteResults

于 2010-12-01T20:33:25.217 に答える
0
        //File is read now, but split later.
        var lines = File.ReadAllLines("accounts.txt").Select(p => p.Split('\t')); 
        //Accounts are new'd up later.
        var accounts = lines.Select(p => new Account(p[0], p[1], p[2], p[3])); 
        //Accounts are Routed later.
        var results = accounts.Select(p => RouteAccount(p)); 
        //Write results list to target file 
        WriteResults("results.txt", results);

    private static void WriteResults(string filename, IEnumerable<Result> results)   
    {   
        //file is split, accounts are new'd up and routed by enumerating results
        List<Result> items = results.ToList();
    }   
于 2010-12-01T22:14:55.477 に答える