我们知道你不能在编译的查询中添加像.Where()
或.First()
这样的额外子句,因为这会更改查询并强制重新编译。我想知道的是哪些方法可用于“关闭”编译的查询。
我知道大多数人都使用.AsEnumerable()
或.ToList()
,但其他哪些方法也可以使用?我可以使用.AsQueryable()
,还是非操作?
哪个性能更好?我知道.AsEnumerable()
比.ToList()
快,但如果我想要IQueryable
,.AsEnumerable().AsQueryable()
比.ToList()
更好吗?
答案 0 :(得分:7)
答案 1 :(得分:1)
哪些方法可用于“关闭”已编译的查询。
返回序列的方法使用延迟执行,除非方法类似于ToXYZ
。 Where
,Select
,Take
,Skip
,GroupBy
和OrderBy
等属于此类。返回单个对象的方法会强制执行查询,例如First
,Single
,ToList
和ToArray
,ToDictionary
,ToLookup
,{{ 1}},Any
等。请参阅此优秀主题:Linq - What is the quickest way to find out deferred execution or not?
我知道大多数人都使用.AsEnumerable()或.ToList(),但其他哪些方法也可以使用?我可以使用.AsQueryable(),还是这是一个无操作?
他们都不同。贾斯汀有一个宏大的解释。您可能还希望看到:What's the difference(s) between .ToList(), .AsEnumerable(), AsQueryable()?,它有一个很好的答案。
通常,您可以通过查看方法本身的名称来理解方法的语义。名为All
的方法意味着它只会将输入作为返回。这可能涉及或不涉及返回新对象,但是以某种方式维护引用。例如,AsSomething
只是对List<T>.AsEnumerable()
进行强制转换(当然它在linq上下文中有更大的意义)。您可以将其强制转换回IEnumerable<T>
并对其进行变异,以反映各处的变化。测试它:
List<T>
虽然看起来像var list = new List<int> { 1, 2 };
var enum = list.AsEnumerable();
var newlist = enum as List<string>;
newlist.Add(3);
//print enum.Count() -> 3
的方法,但是你会得到一个全新的对象,通常会被转换为其他东西。
ToSomething
让我们考虑一下linq背景之外的东西。 var list = new List<int> { 1, 2 };
var newlist = list.ToList();
newlist.Add(3);
//print list.Count -> 2
导致新的字符串表示(字符串无论如何都是不可变的,因此有点无意义)。一个有趣的语义是object.ToString()
返回一个新的List<T>.AsReadonly
实例,但是改变它之外的列表也会改变ReadOnlyCollection<T>
的内部列表,因此命名为ReadOnlyCollection<T>
。
AsReadonly