C# 和 LINQ - 任意语句而不是 let
C# and LINQ - arbitrary statement instead of let
假设我正在执行这样的 LINQ 查询(顺便说一句,这是 LINQ to Objects):
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()
必须 return 一个值,即使我不使用它。如果 returns void
,有没有办法在 LINQ 语句中使用它?我显然不能做这样的事情:
var rows =
from t in totals
Utilities.Sum(t)
select t;
PS - 我知道在 LINQ 表达式中调用具有副作用的方法可能不是好的做法。只是想完全理解 LINQ 语法。
不,没有对 IEnumerable<T>
中的所有项目执行 Action
的 LINQ 方法。它是 very specifically left out,因为设计师积极地不希望它在那里。
回答问题
不,但是你可以通过创建一个 Func
来作弊,它只调用预期的方法并吐出一个随机的 return 值,例如 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;
});
稍微好一点,但仍然在滥用 LINQ。
...但是你应该做什么
但我真的看不出有什么理由不简单地分别循环计算总数:
foreach (var t in totals)
Utilities.Sum(t);
您应该从 Microsoft 的 Reactive Extensions 团队下载 "Interactive Extensions" (NuGet Ix-Main
)。它有很多有用的扩展。它会让你这样做:
var rows =
from t in totals.Do(x => Utilities.Sum(x))
select t;
它允许对遍历的可枚举产生副作用。
请阅读我对问题的评论。实现此类功能的最简单方法是使用如下查询:
var rows = from t in totals
group t by t.name into grp
select new
{
Name = t.Key,
Sum = grp.Sum()
};
以上查询returns IEnumerable object.
更多信息,请参阅:101 LINQ Samples
假设我正在执行这样的 LINQ 查询(顺便说一句,这是 LINQ to Objects):
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()
必须 return 一个值,即使我不使用它。如果 returns void
,有没有办法在 LINQ 语句中使用它?我显然不能做这样的事情:
var rows =
from t in totals
Utilities.Sum(t)
select t;
PS - 我知道在 LINQ 表达式中调用具有副作用的方法可能不是好的做法。只是想完全理解 LINQ 语法。
不,没有对 IEnumerable<T>
中的所有项目执行 Action
的 LINQ 方法。它是 very specifically left out,因为设计师积极地不希望它在那里。
回答问题
不,但是你可以通过创建一个 Func
来作弊,它只调用预期的方法并吐出一个随机的 return 值,例如 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;
});
稍微好一点,但仍然在滥用 LINQ。
...但是你应该做什么
但我真的看不出有什么理由不简单地分别循环计算总数:
foreach (var t in totals)
Utilities.Sum(t);
您应该从 Microsoft 的 Reactive Extensions 团队下载 "Interactive Extensions" (NuGet Ix-Main
)。它有很多有用的扩展。它会让你这样做:
var rows =
from t in totals.Do(x => Utilities.Sum(x))
select t;
它允许对遍历的可枚举产生副作用。
请阅读我对问题的评论。实现此类功能的最简单方法是使用如下查询:
var rows = from t in totals
group t by t.name into grp
select new
{
Name = t.Key,
Sum = grp.Sum()
};
以上查询returns IEnumerable object.
更多信息,请参阅:101 LINQ Samples