我有一个LINQ查询,如下所示:
public IEnumerable<Foo> SelectFooBars()
{
return
from
f in foos
join
b in bars
on f.BarId equals b.Id
select
AddMissingProp(f, b.MissingProp);
}
public void AddMissingProp(Foo foo, string missingProp) // substitute this with inline lambda
{
foo.MissingProp = missingProp;
return foo;
}
我想摆脱AddMissingProp
并在我的select
子句中使用某种形式的lambda。
我试图......
...
select
(f, b) => { f.MissingProp = b.MissingProp; return f }
...但我收到以下错误:
名为'f'的局部变量不能在此范围内声明,因为它会给'f'赋予不同的含义,'f'已在'父或当前'范围内用于表示其他内容。
我如何“lambda-ize”我的查询?
更新
这也不起作用:
...
select
() => { f.MissingProp = b.MissingProp; return f }
我收到以下错误:
join子句中某个表达式的类型不正确。调用“加入”时类型推断失败。
我根本没有改变join
条款,所以我很困惑。
答案 0 :(得分:5)
我认为 icambron 是对的,恕我直言,更好的可读版本是这样的:
var fooBar = from
f in foos
join
b in bars
on f.BarId equals b.Id
select new {f,b};
foreach(var x in fooBar)
x.f.MissingProp = x.b.MissingProp;
// EDIT due to comments: add this if you
// need IEnumerable<Foo> returned
return fooBar.Select(fb => fb.f);
from join select
语句用于查询,不应该误用它们来改变序列的内容。
编辑:这是另一个link提供了一些见解为什么使用ForEach
的功能形式不是一个好主意。
答案 1 :(得分:3)
您可以在lambda表达式中为参数指定类型,但由于您已经在查询中使用了f和b,因此需要使用不同的名称。
(Foo f1,Bar b1)=&gt; ...
修改
return
(
from
f in foos
join
b in bars
on f.BarId equals b.Id
select
new {f, b}
).select(foobar => {foobar.f.BarId = foobar.b.Id; return foobar.f});
答案 2 :(得分:1)
选择 (f2,b2)=&gt; {f2.MissingProp = b2.MissingProp;返回f2}
答案 3 :(得分:1)
使用Lambda语法重写此内容。
var vf2 = foos.Join(bars, f => f.id, b => b.id, (foo, bar) => { foo.MissingProp = bar.MissingProp; return foo; });
如果您需要解释此语法,请与我们联系。
答案 4 :(得分:1)
如果编译器无法推断传递给lambda的正确类型,您当然可以自己指定类型。
这应该可以正常工作:
select
(Foo f2, b) => { f2.MissingProp = b.MissingProp; return f2; }
请注意,正如您已经注意到的那样,您无法重用f
并希望它能保留其含义。这是一个新方法签名,带有新参数,因此您需要为其使用不同的名称。
当你这样做时,你会注意到编译器不能自己弄清楚第一个参数应该是什么类型,但你可以像上面那样指定它。