Linq отложенное исполнение - PullRequest
       25

Linq отложенное исполнение

2 голосов
/ 01 декабря 2010

Я написал простую программу, вот как она выглядит, некоторые детали скрыты:

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 () или забрать результаты заранее, если я знаю, что это проблема, но мне интересно знать, что происходит за кулисами.

Ответы [ 3 ]

4 голосов
/ 01 декабря 2010

Лучше использовать File.ReadLines в .NET 4.0 для ленивого чтения файла.Как и сейчас, чтение файла не откладывается и будет читать весь файл в память, когда вернется File.ReadAllLines.Это произойдет только один раз.

3 голосов
/ 01 декабря 2010

Он не будет читать файл повторно, нет - потому что , что часть выполнения не отложено. Он вернет массив, а затем вызов Select вернет вам последовательность ... проекция будет отложена, но чтение файла не будет. Этот массив будет оставаться в памяти до тех пор, пока все ссылки на него (прямо или косвенно) не будут пригодны для сборки мусора ... ему не нужно будет перечитывать файл.

С другой стороны, вы можете захотите прочитать результаты, используя ToList() или что-то подобное в любом случае - потому что таким образом вы сможете обнаружить любые ошибки до запуска написать результаты. Очень часто хорошей идеей является убедиться, что у вас есть все необходимые данные, прежде чем вы начнете выполнять код с побочными эффектами (что, я думаю, WriteResults делает). Очевидно, что он менее эффективен с точки зрения количества данных, необходимых в памяти за один раз, хотя ... это баланс, который вам придется взвесить самостоятельно.

0 голосов
/ 02 декабря 2010
        //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();
    }   
...