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