选择Linq不呼叫方法

时间:2018-12-20 13:14:23

标签: c# linq

我有此代码Linq c#

from r in Employer.Restrictions 
select new RestrictionDto(r);

雇主限制已注册,但从未调用RestrictionDto的构造函数,仅返回null。我在restrictionDto中放置了一个BreakPoint,并且代码永不停止。

我以前从未见过这个问题。我在代码中有很多类似的代码,并且工作正常。

有人可以帮忙吗?

2 个答案:

答案 0 :(得分:5)

Linq查询是惰性的,也就是说,除非另行通知,否则它们实际上不会执行任何操作。

换句话说,您不是在要求执行查询。如果要执行查询,则必须以ToList或您认为适合于手头任务的任何急切操作结束。

答案 1 :(得分:1)

您必须知道,LINQ语句有两种:

  • 返回IEnumerable<...>(或IQueryable)的人
  • 和那些没有。

第一个组将仅返回一个对象,该对象包含枚举元素所需的所有内容:获取序列的第一个元素,一旦有了一个元素,就可以获取下一个,直到没有其他对象为止左。

注意:通过创建此可枚举的对象,您尚未枚举它。

第二组,不返回IEnumerable<...>的LINQ函数实际上是将开始枚举的函数:ToListToDictionaryFirstOrDefault,{{1 }},CountMax

这些函数使用输入Any来调用IEnumerable,并反复调用GetEnumerator()直到知道返回值为止。通常,需要枚举完整的序列,有时只有其中的几个。

例如:

MoveNext()

返回您的问题

您的代码创建一个public static bool Any<TSource>(this IEnumerable<Tsource> source) { if (source == null) throw new ArgumentNullException(...); IEnumerator<TSource> enumrator = source.GetEnumerator(); bool containsAnyElement = enumerator.MoveNext(); // no need to check the rest of the sequence, I already know the result: return containsAnyElement; } ,它类似于:

IEnumerable<...>

换句话说:创建一个可枚举的对象,对它进行枚举时,将为可枚举序列Employer.Restrictions中的每个限制返回一个新的对象RestrictionDto到在枚举器上调用的每个MoveNext。

因此,您已经创建了Enumerable对象,但尚未对其进行枚举。

尝试以下操作,调试器将向您显示RestrictionDto是实际创建的:

IEnumerable<RestrictionDto> restrictions = Employer.Restrictions
    .Select(restriction => new RescrictionDto(restriction));

他们都将在内部做类似以下的事情:

var list = restrictions.ToList();
bool restrictionsAvailable = restrictions.Any();
var firstRestriction = restrictions.FirsOrDefault();
int numberOfRestrictions = restrictions.Count();
foreach (var restiction in restrictions)
{
    ...
}