如果LINQ的结果具有接口类型,则意味着它具有延迟执行

时间:2018-03-06 11:44:14

标签: c# linq

使用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();

2 个答案:

答案 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之间的区别。