Linq 你要列出()吗?

Linq 你要列出()吗?,linq,linq-to-sql,Linq,Linq To Sql,在处理LINQ查询的结果时,您是否有一个更喜欢使用的默认类型 默认情况下,LINQ将返回一个IEnumerable或一个IORDerenumerable。我们发现列表通常对我们更有用,因此我们习惯了ToList()在大部分时间对查询进行排序,当然在函数参数和返回值中使用List 唯一的例外是在LINQ to SQL中,调用.ToList()会过早地枚举IEnumerable 我们还广泛使用WCF,其默认集合类型是System.Array。为了与代码库的其余部分保持一致,我们总是在VS2008的“

在处理LINQ查询的结果时,您是否有一个更喜欢使用的默认类型

默认情况下,LINQ将返回一个
IEnumerable
或一个
IORDerenumerable
。我们发现
列表
通常对我们更有用,因此我们习惯了
ToList()
在大部分时间对查询进行排序,当然在函数参数和返回值中使用
List

唯一的例外是在LINQ to SQL中,调用
.ToList()
会过早地枚举
IEnumerable

我们还广泛使用WCF,其默认集合类型是
System.Array
。为了与代码库的其余部分保持一致,我们总是在VS2008的“服务参考设置”对话框中将其更改为
System.Collections.Generic.List


您要做什么?

这取决于您是否需要修改集合。当我知道没有人要添加/删除项目时,我喜欢使用数组。当我需要排序/添加/删除项目时,我使用列表。但是,通常我会尽可能地让它保持IEnumerable。

ToList
总是立即计算序列,而不仅仅是在LINQ to SQL中。如果你想要的话,那很好——但这并不总是合适的

就我个人而言,我会尽量避免声明直接返回
List
——通常
IList
更合适,并允许您稍后更改为不同的实现。当然,有些操作只在
列表
本身上指定。。。这种决定总是很棘手的


编辑:(我会把它放在注释中,但它太大了。)延迟执行允许您处理太大而无法放入内存的数据源。例如,如果您正在处理日志文件——将它们从一种格式转换为另一种格式,将它们上载到数据库,计算一些统计数据,或者诸如此类的东西——您很可能能够通过流式传输来处理任意数量的数据,但您确实不想将所有内容都存储在内存中。这可能与您的特定应用程序无关,但需要记住。

我们有相同的场景-WCF与服务器通信,服务器使用LINQtoSQL

我们在从服务器请求对象时使用.ToArray(),因为客户端更改列表是“非法的”。(意思是说,没有支持“.Add”、“.Remove”等的目的)

然而,当仍然在服务器上时,我建议您将其保留为默认值(它不是IEnumerable,而是IQueryable)。这样,如果您想根据某些条件进行更多的筛选,则在计算之前,SQL端的筛选仍然是

这是非常重要的一点,因为它意味着难以置信的性能增益或损失取决于您所做的

例如:

// This is just an example... imagine this is on the server only. It's the
// basic method that gets the list of clients.
private IEnumerable<Client> GetClients()
{
    var result = MyDataContext.Clients;  

    return result.AsEnumerable();
}

// This method here is actually called by the user...
public Client[] GetClientsForLoggedInUser()
{
    var clients = GetClients().Where(client=> client.Owner == currentUser);

    return clients.ToArray();
}
//这只是一个例子。。。假设这仅在服务器上。这是最重要的
//获取客户端列表的基本方法。
私有IEnumerable GetClient()
{
var result=MyDataContext.Clients;
返回结果;
}
//这里的这个方法实际上是由用户调用的。。。
公共客户端[]GetClientsForLoggedInUser()
{
var clients=GetClients().Where(client=>client.Owner==currentUser);
返回clients.ToArray();
}
你看到那里发生了什么吗?“GetClients”方法将强制从数据库下载所有“客户端”。。。然后,Where子句将出现在GetClientsForLoogedInUser方法中,以对其进行筛选

现在,请注意细微的变化:

private IQueryable<Client> GetClients()
{
    var result = MyDataContext.Clients;  

    return result.AsQueryable();
}
private IQueryable GetClients()
{
var result=MyDataContext.Clients;
返回结果。AsQueryable();
}

现在,在调用“.ToArray”之前,不会进行实际的评估。。。SQL将进行过滤。好多了

在Linq to Objects的情况下,从函数返回
List
不如返回
IList
,正如著名的SKEET所指出的那样。但通常你仍然可以做得更好。如果您返回的内容应该是不可变的,那么IList是一个错误的选择,因为它会邀请调用者添加或删除内容

例如,有时您有一个返回Linq查询结果的方法或属性,或者使用
yield return
惰性地生成一个列表,然后您意识到最好在第一次调用时这样做,将结果缓存在
列表中,然后返回缓存的版本。此时返回
IList
可能是个坏主意,因为调用者可能会出于自己的目的修改列表,这将损坏缓存,使其更改对所有其他调用者可见

最好返回
IEnumerable
,这样它们所拥有的就是向前迭代。如果调用者想要快速随机访问,也就是说,他们希望可以使用[]通过索引进行访问,他们可以使用
ElementAt
,Linq定义了
ElementAt
,以便它安静地嗅探
IList
,并在可用时使用它,如果不可用,则执行哑线性查找


我使用
ToList
的一个原因是,我有一个复杂的Linq表达式系统,其中混合了使用
yield-return
过滤或转换列表的自定义运算符。在调试器中单步执行可能会变得非常混乱,因为它在执行惰性计算时会跳转,因此我有时会临时在一些地方添加一个ToList(),以便更轻松地遵循执行路径。(虽然如果你正在执行的事情有副作用,这可能会改变程序的意义。)

如果你不需要列表的附加功能,为什么不坚持IQueryable?!?!?!最小公分母是最好的解决方案(尤其是当你看到蒂莫西的答案时)。

同意托利斯立即进行评估。我们的想法是,在LINQtoSQL中,这可能会对性能产生影响(特别是当我们链接到