在 C#/LINQ 中用匿名方法替换常规方法

发布于 2024-08-17 06:51:42 字数 1052 浏览 3 评论 0原文

我有一个如下所示的 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 化”我的查询?


更新

这也不起作用:

...
select
    () => { f.MissingProp = b.MissingProp; return f }

我收到以下错误:

连接子句中的表达式之一的类型不正确。调用“Join”时类型推断失败。

我根本没有更改 join 子句,所以我很困惑。

I have a LINQ query that looks like this:

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;
}

I would like to get rid of AddMissingProp and use some form of a lambda in my select clause instead.

I attempted...

...
select
    (f, b) => { f.MissingProp = b.MissingProp; return f }

...but I got the following error:

A local variable named 'f' cannot be declared in this scope because it would give a different meaning to 'f', which is already used in a 'parent or current' scope to denote something else.

How can I "lambda-ize" my query?


Update

This also doesn't work:

...
select
    () => { f.MissingProp = b.MissingProp; return f }

I get the following error:

The type of one of the expressions in the join clause is incorrect. Type inference failed in the call to 'Join'.

I didn't change the join clause at all, so I'm perplexed.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

身边 2024-08-24 06:51:42

我认为 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 语句用于查询,它们不应该被滥用来改变序列的内容。

编辑:这是另一个链接提供了一些见解,说明为什么使用 ForEach 的函数形式不是一个好主意。

I think icambron is right, IMHO the better readable version is this:

  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);

The from join select statements are for queries, they should not be misused for mutating the contents of a sequence.

EDIT: Here is another link providing some insights why using a functional form of ForEach is not a good idea.

人心善变 2024-08-24 06:51:42

您可以在 lambda 表达式中为参数指定类型,但需要使用不同的名称,因为您已经在查询中使用了 f 和 b。

(Foo f1, Bar b1) => ...

编辑

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});

You can give types to your parameters in a lambda expression but you need to use different names since you're already using f and b in the query.

(Foo f1, Bar b1) => ...

Edit

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});
月亮邮递员 2024-08-24 06:51:42

选择
(f2,b2)=> { f2.MissingProp = b2.MissingProp;返回 f2 }

select
(f2, b2) => { f2.MissingProp = b2.MissingProp; return f2 }

唐婉 2024-08-24 06:51:42

使用 Lambda 语法重写它。

var vf2 = foos.Join(bars, f => f.id, b => b.id, (foo, bar) => { foo.MissingProp = bar.MissingProp; return foo; });

如果您需要此语法的解释,请告诉我。

Rewrite this with Lambda syntax.

var vf2 = foos.Join(bars, f => f.id, b => b.id, (foo, bar) => { foo.MissingProp = bar.MissingProp; return foo; });

If you need explanation of this syntax, let me know.

债姬 2024-08-24 06:51:42

如果编译器无法推断出传递给 lambda 的正确类型,您当然可以自己指定类型。

这应该可以正常工作:

select
    (Foo f2, b) => { f2.MissingProp = b.MissingProp; return f2; }

请注意,正如您已经注意到的,您不能重用 f 并希望它保留其含义。这是一个新的方法签名,具有新的参数,因此您需要为其使用不同的名称。

当您这样做时,您会注意到编译器无法自行确定第一个参数应该是什么类型,但您可以指定它,就像上面一样。

If the compiler isn't able to infer the correct type to pass to a lambda, you can of course specify the type yourself.

This should work fine:

select
    (Foo f2, b) => { f2.MissingProp = b.MissingProp; return f2; }

Note that as you've already noticed, you cannot reuse fand hope that it will retain its meaning. This is a new method signature, with new parameters, so you need to use a distinct name for it.

When you do, you notice that the compiler isn't able to figure out by itself what type the first argument should be, but you can specify it, like above.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文