扩展方法中的lambda何时做得太多?

时间:2010-10-08 15:02:36

标签: c# linq lambda

我意识到这是部分主观的,但我对社区意见一般都很好奇,并且无法成功找到解决这个问题的现有问题。

我与同事就L2EF查询中的特定Select语句进行了一些宗教辩论。

.Select(r =>
{
    r.foo.Bar = r.bar;
    r.foo.Bar.BarType = r.Alpha;
    if (r.barAddress != null)
    {
        r.foo.Bar.Address = r.barAddress;
        r.foo.Bar.Address.State = r.BarState;
    }
    if (r.baz != null)
    {
        r.foo.Bar.Baz = r.baz;
        if (r.bazAddress != null)
        {
            r.foo.Bar.Baz.Address = r.bazAddress;
            r.foo.Bar.Baz.Address.State = r.BazState;
        }
    }
    return r.foo;
})

警告:

  • 这是Linq-to-Entities
  • 这是数据库中执行并返回
  • 后的工作
  • 输入参数r是匿名的

就个人而言,我认为(a)select子句不应该改变值,它应该仅仅是项目。他的反驳论点是他没有改变任何东西,他只是确保一切都由于数据库查询而被正确初始化。其次,我认为一旦他开始进入完整的代码块并返回语句,就应该定义一个方法,甚至是Func<T, U>,而不是全部内联。这里的复合器同样是输入是匿名的,因此需要定义一个类型。但是,尽管如此,我们仍在辩论一般性观点。

那么,lambda表达式什么时候做的太多了?你在哪里画出沙子中的模糊线?

6 个答案:

答案 0 :(得分:2)

我的第一直觉是与你达成一致,主要是关于规模和复杂性。

但是,它被用在一个上下文中,它将(或有时)执行为除.NET代码之外的其他东西(特别是如果它变成SQL查询的一部分),我会变得更加宽容它的。

所以,这就是我绘制模糊线的地方,也是我再次移动它的原因:)

答案 1 :(得分:1)

我也同意Select()应该用于投影。我宁愿看到使用“let”关键字提前进行检查,以便Select()中的投影可以保持清洁。这将使Select()能够引用使用“let”设置的变量。

答案 2 :(得分:1)

我个人认为这不是一个长长的lambda表达。我想你将会看到更复杂,并且将来会嵌套lambda。特别是像Rx这样的东西。

至于状态变化......好吧,他在这里只是初始化价值观。我只关心它是否将状态分配给lambda之外的某个变量,但这都是r的初始化,所以对我来说似乎很好。

答案 3 :(得分:1)

在看到烦扰我的事情之前,我不得不盯着这一段时间。

  1. 这需要一个重构。

  2. 我花了很长时间才读到了lambda的意图。

  3. 我不确定我是否可以支持你对Select的工作的定义,但我同意你能保持lambda越短越好。如果需要进行dB提取后的初始化,请将其分解以重复使用。

答案 4 :(得分:0)

你必须考虑其他选择......是否有更好的地方来放置这种逻辑。无论哪种方式,你循环遍历LINQ中的每个实体,或者在foreach循环中,来完成额外的工作......除非你想将它重构为你自己的扩展方法,否则我会说如果有效的话就离开它。 / p>

视觉上,它不是那么混乱,所以这是一个加号。或者,您可以看到let关键字(基本上是子查询)是否会为您购买其他内容。

答案 5 :(得分:0)

lambda的长度根本不会打扰我。但是当我在select语句中指定一个值时,我会同意这种污垢的感觉。我会将初始化内容考虑在select语句下面的语句中。