Разделение зависимостей и нечестивых связей - это одна особенность, которая делает его великолепным. Все остальное можно обсуждать и утверждать, что оно выполнимо каким-то домашним способом.
Я проводил рефакторинг немного более сложной системы со старой и тяжелой библиотекой и был заблокирован из-за невозможности разорвать зависимость от времени компиляции - из-за именованного делегата, скрывающегося на «другой стороне». Вся загрузка сборки и отражение не помогли - компилятор отказался бы просто приводить делегат () {...} к объекту, и что бы вы ни делали для его усмирения, оно не сработало бы с другой стороны.
Сравнение типов делегатов, которое является структурным во время компиляции, становится номинальным после этого (загрузка, вызов). Это может показаться нормальным, если вы думаете, что «моя дорогая библиотека будет использоваться навсегда и всеми», но она не масштабируется даже до более сложных систем. Шаблоны Fun <> возвращают степень структурной эквивалентности обратно в мир номинальной типизации. Это тот аспект, которого вы не можете достичь, разворачивая свой собственный.
Пример - преобразование:
class Session (
public delegate string CleanBody(); // tying you up and you don't see it :-)
public static void Execute(string name, string q, CleanBody body) ...
до:
public static void Execute(string name, string q, Func<string> body)
Позволяет полностью независимому коду выполнять вызов отражения, например:
Type type = Type.GetType("Bla.Session, FooSessionDll", true);
MethodInfo methodInfo = type.GetMethod("Execute");
Func<string> d = delegate() { .....} // see Ma - no tie-ups :-)
Object [] params = { "foo", "bar", d};
methodInfo.Invoke("Trial Execution :-)", params);
Существующий код не замечает разницы, новый код не получает зависимости - мир на Земле: -)