Прочитав ответы, а также некоторые связанные вопросы, я собрал свое понимание проблемы здесь.
Как работают методы расширения
Во-первых, важно понимать, что расширения - это просто синтаксический сахар для статических методов.
// Say you have an extension method that looks like this:
class Extensions
{
public static void Extend(this SomeClass foo) {}
}
// Here's how you call it
SomeClass myClass;
myClass.Extend();
// The compiler converts it to this:
Extensions.Extend(myClass);
Метод фактически не становится частью класса.Вот почему вы не можете получить доступ к закрытым членам из метода расширения.Методы расширения изменяют только синтаксис C # и не нарушают концепцию доступности ООП.Фактически, если вы пишете метод расширения и обычный статический метод, которые делают одно и то же, а затем декомпилируете MSIL, они точно такие же .
Почему существуют методы расширения
Так что, если они не добавляют реальной функциональности, зачем вообще использовать методы расширения?Ответ - LINQ:
// LINQ makes this easy to read
array.Where(i => i&1 == 0).Select(i => i*i);
// Without extension methods, we would have to do it like this
Enumerable.Select(Enumerable.Where(array, i => i&1 == 0), i => i*i);
В некотором смысле, все LINQ - просто синтаксический сахар, поскольку все, что он может сделать, может быть написано неуклюжим, не LINQy способом.Очевидно, что команда C # чувствовала, что читаемость, достигнутая LINQ, стоила того, но напрашивается вопрос: «Почему они остановились на этом?»
Почему не другие типы расширений?
Эрик Липперт,один из разработчиков компилятора C #, описанный в сообщении в блоге о том, что огромная часть C # 3 создавала все конструкции, необходимые для LINQ: "неявно типизированных локальных элементов, анонимных типов, лямбда-выражений, расширенийметоды, инициализаторы объектов и коллекций, понимание запросов, деревья выражений и [и] улучшенный вывод типов методов. " Поскольку команда C # была самой ограниченной группой ресурсов для выпуска 2008 .NET, дополнительные типы расширений, которые не былиt строго необходимые для LINQ не были включены.
Команда решила реализовать свойства расширения в C # 4 и фактически написала рабочий прототип, но он был отброшен, когда обнаружил, что команда WPF не будет реализована как реализованная (который был одним из мотиваторов для функции).Позже Эрик Липпер сказал, что они рассмотрели методы расширения для статических классов, но не смогли оправдать реальные выгоды от затрат на внедрение, тестирование и обслуживание.
Обходное решение
Можно написать метод расширения, который приближается:
public static TResult DoSomething<TType, TResult>(this TType @class)
{
// access static methods with System.Reflection
return default(TResult);
}
// This works, but poorly
typeof(Math).DoSomething();
typeof(Convert).DoSomething();
Но это довольно уродливо.Он требует рефлексии и не может поддерживать интеллектуальную типизацию, поскольку любой Type
может вызывать его, и это, скорее всего, не та функциональность, для которой он предназначен.