C#和LINQ - 任意语句而不是let

时间:2015-02-12 20:56:53

标签: c# .net linq linq-to-objects

假设我正在做这样的LINQ查询(这是LINQ to Objects,BTW):

var rows = 
    from t in totals
    let name = Utilities.GetName(t)
    orderby name
    select t;

因此,GetName方法只是从Total对象计算显示名称,并且可以正确使用let关键字。但是,假设我有另一种方法Utilities.Sum(),它在Total对象上应用一些数学并在其上设置一些属性。我可以使用let来实现这一点,如下所示:

var rows =
    from t in totals
    let unused = Utilities.Sum(t)
    select t;

这里奇怪的是,Utilities.Sum()必须返回一个值,即使我不使用它。如果它返回void,有没有办法在LINQ语句中使用它?我显然不能做这样的事情:

var rows =
    from t in totals
    Utilities.Sum(t)
    select t;

PS - 我知道在LINQ表达式中调用带副作用的方法可能不是良好的练习。只是试图完全理解LINQ语法。

4 个答案:

答案 0 :(得分:3)

不,没有LINQ方法对Action中的所有项目执行IEnumerable<T>。这是very specifically left out,因为设计师积极地不希望它在那里。

答案 1 :(得分:2)

回答问题

不,但您可以通过创建Func来欺骗,该bool只调用预期的方法并吐出随机返回值,例如Func<Total, bool> dummy = (total) => { Utilities.Sum(total); return true; }; var rows = from t in totals let unused = dummy(t) select t;

statement

但这不是一个好主意 - 它不是特别易读。


让幕后的var rows = totals.Select(t => new { t, unused = dummy(t) }) .Select(x => x.t);

上述查询将转换为与此类似的内容:

var rows = totals.Select(t =>
               {
                   Utilities.Sum(t);
                   return t;
               });

如果你想使用方法语法而不是查询语法,那么另一个选择是,你可以做的是:

foreach (var t in totals)
    Utilities.Sum(t);

好一点,但仍在滥用LINQ。


......但你应该做什么

但我真的认为没有理由不单独循环总计:

{{1}}

答案 2 :(得分:0)

您应该下载&#34; Interactive Extensions&#34; (来自Microsoft的Reactive Extensions团队的NuGet Ix-Main)。它有很多有用的扩展。它可以让你这样做:

var rows =
    from t in totals.Do(x => Utilities.Sum(x))
    select t;

它允许对遍历的可枚举的副作用。

答案 3 :(得分:-1)

请阅读我对这个问题的评论。实现此类功能的最简单方法是使用如下查询:

var rows = from t in totals
    group t by t.name into grp
    select new 
    {
        Name = t.Key,
        Sum = grp.Sum()
    };

上面的查询返回 IEnumerable 对象。

有关详细信息,请参阅:101 LINQ Samples