Linq延迟执行
我写了一个简单的程序,下面是它的样子,隐藏了一些细节:Linq延迟执行,linq,linq-to-objects,deferred-execution,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
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 ...
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.IO;
命名空间路由计数
{
班级计划
{
静态void Main(字符串[]参数)
{
//从源文件中绘制线
var lines=File.ReadAllLines(“accounts.txt”).Select(p=>p.Split('\t'));
//将行转换为帐户
var账户=行。选择(p=>新账户(p[0],p[1],p[2],p[3]);
//向路由器提交帐户
var结果=账户。选择(p=>RouteAccount(p));
//将结果列表写入目标文件
WriterResults(“results.txt”,results);
}
私有静态void WriteResults(字符串文件名、IEnumerable结果)
{
…磁盘写入调用。。。
}
私有静态结果RouteAccount(帐户)
{
…服务电话。。。
}
}
}
我的问题是——显然,当从数据上下文中选择时,执行会延迟。如果您注意到,在“Main”函数的第一条语句中,我是从File.ReadAllLines(“accounts.txt”)查询的。这是一个错误的选择吗?如果我列举最后的结果,这句话会重复吗
如果我知道这是一个问题,我可以简单地使用.ToArray()或提前获取结果,但我很想知道幕后发生了什么。最好使用.NET 4.0中的
File.ReadLines
来延迟读取文件。现在,文件的读取不会延迟,当file.ReadAllLines
返回时,会将整个文件读取到内存中。这只会发生一次。不会重复读取文件,不会-因为执行的这一部分不会延迟。它将返回一个数组,然后调用Select
将返回一个序列。。。投影将被延迟,但文件的读取不会延迟。该数组将保留在内存中,直到(直接或间接)引用它的所有内容都符合垃圾收集条件。。。它不需要重新读取该文件
另一方面,您可能希望使用ToList()
或类似的方法读取结果,因为这样,您就可以在开始编写结果之前找出任何错误。在开始执行带有副作用的代码之前(我想,WriteResults
会产生副作用),确保您已经获得了所需的所有数据通常是一个好主意。很明显,就每次内存中需要的数据量而言,它的效率较低。。。这是一个天平,您必须自己称重。//文件现在读取,但稍后拆分。
//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();
}
var lines=File.ReadAllLines(“accounts.txt”).Select(p=>p.Split('\t'));
//以后会有新的账户。
var账户=行。选择(p=>新账户(p[0],p[1],p[2],p[3]);
//账户将在稍后发送。
var结果=账户。选择(p=>RouteAccount(p));
//将结果列表写入目标文件
WriterResults(“results.txt”,results);
私有静态void WriteResults(字符串文件名、IEnumerable结果)
{
//文件被拆分,帐户被新建,并通过枚举结果进行路由
列表项=results.ToList();
}
谢谢你的回答,但是你能告诉我是如何决定是否延期的吗?这将是有益的information@Eugarps当前位置没有规则。可以看出,File.ReadAllLines
不会延迟,因为它返回一个数组。但是仅仅因为一个方法返回IEnumerable
,并不意味着它被延迟(它返回的具体对象可以是,比如说,一个列表
)。方法返回IEnumerable
是一个提示,它可能会被延迟,但不是一个保证。此外,延迟执行和延迟执行之间有着巨大的区别(想想看Enumerable.OrderBy
,它是延迟的,但不是延迟的)。我被分为你的答案和Jon的答案,但我投票支持他,因为这是最先发生的。在您的回复中,特别有用的是引用了ReadLines,我不知道这一点,但非常符合我的目的。这是一个很好的建议,我在LINQ中遇到了一些问题,延迟执行实际上导致异常被抛出到我不希望处理它们的地方。