Методы расширения являются статическими, и вы не можете переопределить статический метод. Вы также не можете "переопределить" фактический метод экземпляра статическим / расширением.
Вам нужно будет явно использовать оптимизированное расширение. Или неявно, ссылаясь на пространство имен вашего собственного расширения вместо System.Linq
.
Или явно проверьте тип в вашем расширении и вызовите правильный тип в зависимости от типа среды выполнения.
Это похоже на проблему, лучше подходящую для наследования, чем методы расширения. Если вам нужны другие функции в зависимости от типа среды выполнения, сделайте базовый метод виртуальным и переопределите его в производных классах.
Я вижу много путаницы в этом аспекте методов расширения. Вы должны понимать, что они не миксины, они на самом деле не попадают в класс. Это просто синтаксический сахар, который компилятор распознает и «позволяет» выполнить его, как если бы это был обычный метод экземпляра. Представьте, что это был не метод расширения, а просто статический метод:
public static void BlowHorn (IBoat boat) {
Console.WriteLine ("Patched on horn for {0}: TWEET", boat.GetType().Name);
}
Как бы вы "переопределили" этот метод из реализации IBoat
? Ты не можешь Единственное, что вы можете сделать, это включить проверку типов в этот статический метод или написать некоторый код вызова динамического метода, используя блок dynamic
в C # 4 или Reflection в более ранних версиях.
Чтобы сделать это еще более понятным, взгляните на этот код класса System.Linq.Enumerable
из Reflector:
public static TSource ElementAt<TSource>(this IEnumerable<TSource> source,
int index)
{
TSource current;
if (source == null)
{
throw Error.ArgumentNull("source");
}
IList<TSource> list = source as IList<TSource>;
if (list != null)
{
return list[index];
}
// ...
}
Это один из основных методов расширения в .NET Framework. Это позволяет оптимизировать, явно проверяя, реализует ли параметр IList<T>
. Кроме этого, он не может знать, поддерживает ли базовый конкретный тип на самом деле индексированный доступ. Вы должны сделать это так же; создайте другой интерфейс, например IHorn
или что-то еще, и в вашем расширении проверьте, реализует ли IBoat
также IHorn
, так же, как класс Enumerable
здесь.
Если вы не управляете кодом для IBoat
классов или методов расширения, то вам не повезло. Если вы это сделаете, то используйте многоинтерфейсное наследование, явную проверку типов или динамический код - это ваши варианты.