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

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

于 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 回答