.AsEnumerable()
是IEnumerable<T>
上的一种扩展方法。此方法将调用它的可枚举对象转换为IEnumerable<T>
的实例。但是,由于对象必须实现IEnumerable<T>
才能应用于此扩展方法,因此转换为IEnumerable<T>
很简单,只需转换为IEnumerable<T>
即可。我的问题是,为什么会存在这种方法?
示例:
List<string> strings = new List<string>() { "test", "test2", "test3" };
IEnumerable<string> stringsEnum1 = strings.AsEnumerable();
IEnumerable<string> stringsEnum2 = (IEnumerable<string>)strings;
在上面的示例中,stringsEnum1
和stringsEnum2
是等效的。扩展方法的意义是什么?
编辑:作为推论,为什么在转换为IQueryable<T>
时会有.AsQueryable()
方法?
发布于 2010-01-06 23:15:41
可读性是这里的主要问题。考虑一下这点
Table.AsEnumerable().Where(somePredicate)
的可读性远远高于
((IEnumerable<TableObject>)Table).Where(somePredicate).
或者想象一下,想要在SQL Server上执行查询的一部分,其余的在内存中执行:
Table.Where(somePredicate)
.Select(someProjection)
.AsEnumerable()
.SomethingElse()
对比
((IEnumerable<SomeProjectionType>)Table.Where(somePredicate)
.Select(someProjection))
.SomethingElse()
现在,至于为什么这样的方法是有用的,想想LINQ to SQL DataContext
中的Table
的例子。由于Table
是一个IQueryable
,因此它实现了IEnumerable
。当您在这样的Table
上调用Where
方法并枚举结果时,将执行最终导致在SQL Server上执行SQL语句的代码。AsEnumerable
所做的是,不,我不想使用LINQ to SQL提供程序来执行Where
,我想使用Where
的LINQ to Objects实现。
因此枚举了
Table.Where(somePredicate)
导致在SQL Server上执行查询,而枚举
Table.AsEnumerable().Where(somePredicate)
将Table
表示的表放入内存中,并在内存中(而不是在SQL Server上!)执行Where
功能。
这就是AsEnumerable
的意义所在:允许您隐藏IEnumerable
方法的特定实现,而使用标准实现。
发布于 2010-01-06 23:46:09
除了可读性之外,我还想到了一个与查询实现相关的原因:在通过另一个Linq提供程序返回的匿名类型上使用Linq to对象。您不能强制转换为匿名类型(或匿名类型的集合),但可以使用.AsEnumerable()
为您执行强制转换。
示例:
// Get an IQueryable of anonymous types.
var query = from p in db.PeopleTable /* Assume Linq to SQL */
select new { Name = p.Name, Age = p.Age };
// Execute the query and pull the results into an IEnumerable of anonymous types
var @enum = query.AsEnumerable();
// Use Linq to Objects methods to further refine.
var refined = from p in @enum
select new
{
Name = GetPrettyName(p.Name),
DOB = CalculateDOB(p.Age, DateTime.Now)
};
很明显,这里的原因是我们想要使用像Linq to SQL这样的东西将一些记录拉入匿名类型,然后在客户端使用Linq to对象执行一些自定义逻辑(通过Linq to SQL是不可能的)。
转换为IEnumerable<_anon>
是不可能的,所以.AsEnumerable()
是唯一的方法。
感谢每一位回复帮助我拼凑这些东西的人。=)
发布于 2017-01-06 17:33:03
因为我正在读C# 6.0 in a Nutshell
这本书。下面是本书中的AsEnumerable
示例。
其目的是将IQueryable<T>
序列强制转换为IEnumerable<T>
,强制后续查询操作符绑定到可枚举操作符,而不是可查询操作符。这会导致查询的其余部分在本地执行。
为了进行说明,假设我们在SQL Server中有一个MedicalArticles
表,并且希望使用LINQ To SQL或EF来检索摘要少于100个单词的所有关于流感的文章。对于后一个谓词,我们需要一个正则表达式:
Regex wordCounter = new Regex (@"\b(\w|[-'])+\b");
var query = dataContext.MedicalArticles
.Where (article => article.Topic == "influenza" &&
wordCounter.Matches (article.Abstract).Count < 100);
问题是SQL Server不支持正则表达式,因此LINQ- to -db提供程序将抛出异常,抱怨查询无法转换为SQL。我们可以通过两个步骤进行查询来解决这个问题:首先通过LINQ to SQL查询检索所有关于流感的文章,然后在本地过滤少于100字的摘要:
Regex wordCounter = new Regex (@"\b(\w|[-'])+\b");
IEnumerable<MedicalArticle> sqlQuery = dataContext.MedicalArticles
.Where (article => article.Topic == "influenza");
IEnumerable<MedicalArticle> localQuery = sqlQuery
.Where (article => wordCounter.Matches (article.Abstract).Count < 100);
使用AsEnumerable,我们可以在单个查询中完成相同的操作:
var query = dataContext.MedicalArticles
.Where (article => article.Topic == "influenza")
.AsEnumerable()
.Where (article => wordCounter.Matches (article.Abstract).Count < 100);
调用AsEnumerable的另一种方法是调用ToArray或ToList。 AsEnumerable的优势在于它不会强制执行立即查询,也不会创建任何存储结构。
https://stackoverflow.com/questions/2013846
复制相似问题