我写了一个简单的程序,这是它的样子,隐藏了一些细节:
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()或提前获取结果,如果我知道这是一个问题,但我很想知道幕后发生了什么。
答案 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();
}