Использование условного оператора в выражении лямбда в ForEach() в общем списке?

Нельзя ли иметь условный оператор в выражении лямбда в ForEach?

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 += "");

Ошибка компиляции → "В качестве оператора можно использовать только присваивание, вызов, приращение, декремент и новые объектные выражения

Попытка использовать нормальный, если не работает:

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

Просто невозможно?

Ответ 1

Вы используете более короткую форму лямбда-выражений, которые допускают только одно выражение.
Вам нужна длинная форма, которая допускает несколько операторов.

Например:

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

Результатом этого является "Item я Care About, Item я Care About, Item я Care About".

Примечание. Агрегат - отличный способ обеспечить отсутствие трейлинга ","

Ответ 3

Проблема заключалась в том, что выражение

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

не является выражением. Он просто возвращает значение, имеющее тип string.

Есть трюк, чтобы заставить его работать (просто для удовольствия):

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

Я просто добавил вызов метода .GetType() для создания оператора из исходного выражения и скомпилировал его.

Ответ 4

Попробуйте скобки:

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

+ = имеет более высокий приоритет, чем?, возможно, поэтому вы получаете ошибку. С круглыми скобками ошибка может исчезнуть. Не 100% уверены в этом, хотя... лямбда-выражения могут иметь дополнительные ограничения, которые предотвращают использование операторов присваивания.

ОБНОВЛЕНИЕ:

Вместо нескольких инструкций + = намного чище поставить условие в правую часть задания, например:

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 (который я только что видел, поскольку я собирался опубликовать это), даже лучше, чем мой пример, поскольку он касается удаления Терминал ",". Посмотрите на его ответ...: -)