Как переопределить существующий дополнительный метод

Нет, это не имеет никакого значения. От спецификация языка, разделите 9.5 :

Интерфейсы могут содержать объявления типа элемента ( В§8.5 ). Объявление типа элемента в интерфейсе неявно static и public.

59
задан Stefanos Kargas 10 October 2013 в 16:15
поделиться

3 ответа

ОБНОВЛЕНИЕ: Этот вопрос был темой моего блога в декабре 2013 года . Спасибо за отличный вопрос!


В каком-то смысле вы можете это сделать. Но я должен начать с краткого описания основного принципа проектирования разрешения перегрузки в C #. Всякое разрешение перегрузки, конечно же, заключается в том, чтобы взять набор методов с тем же именем и выбрать из этого набора уникальный лучший член для вызова.

Есть много факторов, влияющих на определение «лучшего» метода; разные языки используют разную «смесь» факторов, чтобы понять это. В C # особенно важна "близость" данного метода к месту вызова. Если предоставляется выбор между применимым методом в базовом классе или новым применимым методом в производном классе, C # берет класс производного класса, потому что он ближе, даже если тот, который находится в базовом классе, во всех остальных отношениях лучше соответствует.

Итак, мы просматриваем список. Производные классы ближе, чем базовые классы. Внутренние классы ближе, чем внешние. Методы в иерархии классов ближе, чем методы расширения.

А теперь мы подошли к вашему вопросу. Близость метода расширения зависит от (1) того, сколько пространств имен «вне» нам нужно было пройти? и (2) нашли ли мы метод расширения через с помощью или он был прямо там, в пространстве имен? Поэтому вы можете повлиять на разрешение перегрузки, изменив пространство имен, в котором отображается ваш статический класс расширения, чтобы поместить его в более близкое пространство имен к месту вызова. Или вы можете изменить свой , используя объявления , чтобы поместить с использованием пространства имен, которое содержит требуемый статический класс, ближе, чем другой.

Например, если у вас есть

namespace FrobCo.Blorble
{
  using BazCo.TheirExtensionNamespace;
  using FrobCo.MyExtensionNamespace;
  ... some extension method call
}

, то будет неоднозначно, который ближе. Если вы хотите установить приоритет своего над их собственным, вы можете сделать следующее:

namespace FrobCo
{
  using BazCo.TheirExtensionNamespace;
  namespace Blorble
  {
    using FrobCo.MyExtensionNamespace;
    ... some extension method call
  }

И теперь, когда разрешение перегрузки идет на разрешение вызова метода расширения, сначала идут классы в Blorple , затем классы в ] FrobCo.MyExtensionNamespace , затем классы в FrobCo , а затем классы в BazCo.TheirExtensionNamespace .

Это ясно?

102
ответ дан 24 November 2019 в 18:12
поделиться

Методы расширения нельзя переопределить, поскольку они не являются методами экземпляра и не виртуальны.

Компилятор будет жаловаться, если вы импортируете оба класса методов расширения через пространство имен, поскольку он не будет знать, какой метод вызвать:

Вызов неоднозначен для следующих методов или свойств: ...

Единственный способ обойти это вызов вашего метода расширения с использованием обычного синтаксиса статического метода. Поэтому вместо этого:

a.Foo();

вам нужно будет сделать следующее:

YourExtensionMethodClass.Foo(a);
28
ответ дан 24 November 2019 в 18:12
поделиться

Методы расширения - это в основном статические методы, поэтому я не знаю, как вы можете их переопределить, но если вы просто поместите их в другое пространство имен, вы можете вызвать свое вместо того, которое хотите для замены.

Но Мэтт Манела говорит о том, что методы экземпляра имеют приоритет над методами расширения: http://social.msdn.microsoft.com/forums/en-US/csharplanguage/thread/e42f1511-39e7-4fed-9e56-0cc19c00d33d

Дополнительные идеи о методах расширения вы можете найти на http://gen5.info/q/2008/07/03/extension-methods-nulls-namespaces-and-precedence-in-c/

Редактировать: Я забыл о проблеме двусмысленности, поэтому лучше всего попробуйте не включать методы расширения, которые вы хотите заменить. Таким образом, вам может потребоваться не использовать директиву using, а просто ввести полное имя пакета некоторых классов, и это может решить проблему.

4
ответ дан 24 November 2019 в 18:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: