Изучая лямбда выражения наткнулся на делегаты Action и Func. Зачем нужен второй я понял, хотя бы для : Func summ = (x, y) => x + y Console.WriteLine(summ(10,20)) Но для чего нужен пустой Action непонятно. Приведите простенький пример зачем он может понадобиться ? И почему нельзя поставить void в Func и получить тот же самый Action вида Func например?
Ответ Существует два мира - мир чистого функционального программирования и реальный. В чистом мире чистого функционального программирования не существует изменяемого состояния и не существует операторов (statements), а все является выражением. В этом идеальном мире у функций нет побочных эффектов, а любая конструкция в языке программирования является выражением (т.е. возвращает результат). Но в реальном мире - все по другому. В реальном мире, а особенно в мире C#, есть побочные эффекты и есть замечательный тип Void, который является необычным типом, не совместимым с другими. В этом мире действие (Action) не может быть выражено через функцию (Func), просто потому, что Func запрещен, а тип Unit (аналогичный типу Void, но приводимый к обобщенному типу T) отсутствует. Если бы это было не так, то следующий код был бы валиден: Func fun = n => System.Console.WriteLine(n) Это не значит, что данное правило универсально для всех языков реального мира, и даже для мира .NET, но для C# - это так. Тот же F# (язык более близкий к математическому миру) имеет тип Unit и умеет автоматически конвертировать .NET-ый Void в Unit, что делает приведенный код валидным. TL DR Func запрещен по историческим причинам (что жалко), поскольку очень часто приходится городить конвертер, который преобразует Func, в Action и отбросит результат. Если же говорить о реальные сценарии, то с применимостью типов Action проблем никаких. Parallel.For/Parallel.ForEach: Parallel.For(0, list.Count, n => Console.WriteLine(list[n]) Похоже с предыдущим - ActionBlock и действие, которое должно выполняться разумным числом потоков. Task и действие, которое должно быть выполнено асинхронно: var task = Task.Run(() => SomeOperation()) Всяческие коллбеки для логгирования и прочих операций, которые ничего не возвращают. В общем, наличие и популярность void-return функций определяет применимость Action. По хорошему, нам стоит стараться свести побочные эффекты к разумному минимуму, но в реальном мире, этот минимум никогда не станет 0.