Linq推迟执行

时间:2010-12-01 20:28:04

标签: linq linq-to-objects deferred-execution

我写了一个简单的程序,这是它的样子,隐藏了一些细节:

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”)。这是一个糟糕的选择吗?如果我列举最终结果,这个陈述会重复吗?

我可以简单地.TaArray()或提前获取结果,如果我知道这是一个问题,但我很想知道幕后发生了什么。

3 个答案:

答案 0 :(得分:4)

最好在.NET 4.0中使用File.ReadLines来获取文件的延迟读取。就像现在一样,文件的读取不会延迟,并且会在File.ReadAllLines返回时将整个文件读入内存。这只会发生一次。

答案 1 :(得分:3)

它不会重复读取文件,不会 - 因为 部分执行不是延迟。它将返回一个数组,然后调用Select将返回一个序列... 投影将被延迟,但文件的读取不会。该数组将保留在内存中,直到所有引用它(直接或间接)都符合垃圾收集的条件......它不需要重新读取文件。

另一方面,你可能想要使用ToList()或类似的东西来阅读结果 - 因为这样,你可以找到之前的任何错误WriteResults这样做)。显然,就内存中所需的数据量而言,它在效率方面效率较低......但这是一个平衡,你必须自己衡量。

答案 2 :(得分: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();
    }