在通用列表的 ForEach() 中的 lambda 表达式中使用条件运算符?

Posted

技术标签:

【中文标题】在通用列表的 ForEach() 中的 lambda 表达式中使用条件运算符?【英文标题】:Using conditional operator in lambda expression in ForEach() on a generic List? 【发布时间】:2010-12-21 11:19:49 【问题描述】:

ForEach 的 lambda 表达式中不允许有条件运算符吗?

List<string> items = new List<string>"Item 1", "Item 2", "Item I Care About";

string whatICareAbout = "";

// doesn't compile :(
items.ForEach(item => item.Contains("I Care About") ? 
whatICareAbout += item + "," : whatICareAbout += "");

编译错误->“只有赋值、调用、递增、递减、新对象表达式可以作为语句使用”

尝试使用正常的 if 也不起作用:

// :(
items.ForEach(item => if (item.Contains("I Care About")) whatICareAbout += item + ", ";

不可能吗?

【问题讨论】:

Sheesh 我对答案印象非常深刻,所有这些都在几分钟之内提问:) 我认为@SLaks 回答了我的问题的意图,但 Aggregate() 让我大吃一惊! :) 再次感谢大家:) 您有一个字符串表达式作为一种条件运算符,并且您需要为您的 .ForEach() 方法添加一个语句。这就是出现编译错误的原因。 @Roman - 我现在明白了!我想到一个? x: y 是 if (a) x else y but ?返回 x 和 y 的值,在这种情况下是一个字符串... 【参考方案1】:

您使用的是较短形式的 lambda 表达式,它只允许单个表达式。 您需要长格式,它允许多个语句。

例如:

items.ForEach(item => 
    if (item.Contains("I Care About")) 
        whatICareAbout += item + ", ";
);

【讨论】:

【参考方案2】:

你想达到什么目的?您是否试图形成一串逗号分隔的项目,其中它们包含特定值?在 linq 中,您可以使用以下方法实现此目的:

 List<string> items = new List<string>  "Item 1", "Item 2", "Item I Care About", "Item I Care About", "Item I Care About" ; 
 string whatICareAbout = items.Where(x => x.Contains("I Care About"))
                              .Aggregate( (y, z) => y + ", " + z);

输出是“我关心的项目,我关心的项目,我关心的项目”。

注意:聚合是确保没有尾随“,”的好方法

【讨论】:

使用Aggregate 进行sting concat 是一个我没有想到的非常巧妙的想法。您可以轻松地将其更改为使用StringBuilder,因为StringBuilder 具有流畅的界面。 哈哈,我只是在我的初始答案中添加了一个 Aggregate() 代码示例......但我更喜欢你的。 +1 !【参考方案3】:

问题是那个表达式

item.Contains("I Care About") ? whatICareAbout += item + "," : whatICareAbout += ""

不是陈述。它只返回一个类型为 string 的值。

有一个技巧可以让它发挥作用(只是为了好玩):

    items.ForEach(item => (item.Contains("I Care About") ?
    whatICareAbout += item + "," : whatICareAbout += "").GetType());

我只是添加了对.GetType() 方法的调用,以从初始表达式创建一个语句,然后它被编译。

【讨论】:

对于.ForEach(),你需要一个声明:)【参考方案4】:

试试括号:

items.ForEach(item => item.Contains("I Care About") ? (whatICareAbout += item + ",") : (whatICareAbout += "") );

+= 的优先级高于 ?,这可能就是您收到错误的原因。使用括号,错误可能会消失。不过,这不是 100% 确定的...... lambda 表达式可能有额外的限制,阻止使用赋值语句。

更新:

将条件放在赋值的右侧比使用多个 += 语句更简洁,如下所示:

List<string> items = new List<string>  "one", "two", "three" ;
string whatICareAbout = "";
items.ForEach(item => whatICareAbout +=  item.Contains("I Care About") ? (item + ",") : ""); 

更新 2:

但最好只使用 Aggregate(),因为它正是为这种情况而设计的。这是一个示例:

string whatICareAbout = items.Aggregate("", (total, item) => item.Contains("I Care About") ? (total + item + ",") : total);

但我认为上面的@Matt Breckon's 答案(我在即将发布此内容时刚刚看到)甚至比我的示例更好,因为它涉及删除终端“,”。看看他的回答... :-)

【讨论】:

以上是关于在通用列表的 ForEach() 中的 lambda 表达式中使用条件运算符?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不使用 foreach 的情况下将 ArrayList 转换为强类型泛型列表?

同一列表中的多个 ForEach 与具有一个 ForEach 的多个列表

将 DataTable 转换为通用列表?

PowerShell 中的嵌套 ForEach()

c:forEach 不遍历 TabView 中的列表

利用LinQ技术和lambd表达式进行增删改查