我有2个obj1和的列表obj2
var list1 = new List<obj1>();
var list2 = new List<obj2>();
Run Code Online (Sandbox Code Playgroud)
obj1和obj2共享一个名为name的字符串属性,我需要通过list2中可用的name属性值过滤list1,所以我做了以下操作
var filteredlist = list1.Where(o => list2.Select(o2 => o2.name)
.Distinct()
.Contains(o.name));
Run Code Online (Sandbox Code Playgroud)
以上Linq查询等于以下?
var distinctNames = list2.Select(o2 => o2.name).Distinct();
var filteredlist = list1.Where(o => distinctNames.Contains(o.name));
Run Code Online (Sandbox Code Playgroud)
我的问题是在第一个查询中clr制作一个临时变量来保存distinctNames,即使我没有像第二个查询那样自己创建它吗?或者它会在每次迭代时从list2重做Select Distinct吗?
如果它不创建临时变量,你会如何在一行中编写此查询?
LINQ只是IEnumerable接口上定义的一组扩展方法,因此它不是"CLR如何做到这一点"的问题.您的LINQ查询将等效于
Func<bool> innerAction = list2.Select(o2 => o2.name).Distinct().Contains(o => o.name);
foreach(var e1 in list1)
{
bool condition = innerAction();
if (condition)
{
yield return e1;
}
}
Run Code Online (Sandbox Code Playgroud)
然后,选择查询将是类似的
Func<TIn, TOut> selectFunction = e => e.name;
foreach(var e2 in list2)
{
yield return selectFunction(e2);
}
Run Code Online (Sandbox Code Playgroud)
结果将传递给distinct函数,这是另一个foreach循环,并将传递给contains函数,这将导致另一个foreach循环.
所以你的问题的答案是"是的,它们或多或少相当",但它涉及很多lambdas :)并且"是的,它将重做Distinct每次迭代",因为它再次调用生成的lambda.您最好innerAction通过ToArray()或ToList()(在您的情况下,在where条件的内部操作上调用它)强制评估我的第一个列表.