使用LINQ我发现当LINQ表达式的结果具有接口类型时,它意味着它具有延迟执行。我是对的吗?
例如:
List<int> numbers = new List<int>() { 1, 2, 3, 4, 5 };
// Deferred execution because res1 has an IEnumerable<int> type
var res1 = numbers.Where(x => x > 2);
// Immediate execution because res2 has an int[] type
var res2 = numbers.Where(x => x > 2).ToArray();
答案 0 :(得分:3)
不正确,即使数组实现IEnumerable<int>
。您不知道该类型是否使用延迟执行,因为没有IDeferred
接口。
我认为你能做的最好的事情是尝试将其投放到ICollection<T>
或ICollection
:
public static bool IsDeferred<T>(this IEnumerable<T> source) {
if (source == null) throw new ArgumentNullException(nameof(source));
ICollection<T> genCollection = source as ICollection<T>;
if (genCollection != null) return false;
ICollection collection = source as ICollection;
if (collection != null) return false;
return true;
}
var arr = new int[5];
bool deferred = arr.IsDeferred(); // false
IEnumerable<int> seq = arr.Where(i => i != 0);
deferred = seq.IsDeferred(); // true
答案 1 :(得分:1)
那不对
如果你有一个IQueryable,那将创建一个Expression<Func<T, bool>>
,它会延迟执行。你拥有的是一种表达方式。
如果你有一个IEnumerable,它可以是一个列表,一个数组或其他任何东西。或者它甚至可以是一个返回IEnumerable的函数,最终会得到一个Func<T, bool>
,一旦你访问它就会被执行。
如果你有类似的东西,这可能是一个陷阱
private IEnumerable<Test> GetTests()
{
return _context.Set<Test>();
}
你做了
var tests = GetTests().Take(100);
这里你实际上有一个Func<T, bool>
。您将从db中获取所有记录,然后在内存中执行Take(100)
。
如果你这样做
var tests = GetTests().AsQueryable().Take(100);
现在你有Expression<Func<T, bool>>
延期执行。 {D}服务器上将发生Take(100)
或者您可以首先返回IQueryable而不是IEnumerable。我只想表明2之间的区别。