Проблемы с расширением
Скажем, у меня есть 2 метода расширения для строки, в 2 разных пространствах имен:
namespace test1
{
public static class MyExtensions
{
public static int TestMethod(this String str)
{
return 1;
}
}
}
namespace test2
{
public static class MyExtensions2
{
public static int TestMethod(this String str)
{
return 2;
}
}
}
Эти методы, например, на самом деле ничего не делают.
Теперь рассмотрим этот фрагмент кода:
using System;
using test1;
using test2;
namespace blah {
public static class Blah {
public Blah() {
string a = "test";
int i = a.TestMethod(); //Which one is chosen ?
}
}
}
Вопрос:
Я знаю, что будет выбран только один из методов расширения.
Кто это будет? и почему?
Edit:
Это также беспокоит меня, но не так много, потому что это статический метод в статическом классе:
Как я могу выбрать определенный метод из определенного пространства имен?
Обычно я использую Namespace.ClassNAME.Method()
... Но это просто превосходит всю идею методов расширения. И я не думаю, что вы можете использовать Variable.Namespace.Method()
Ответы
Ответ 1
У меня был этот точный вопрос, поэтому я нашел этот пост два года спустя. Тем не менее, я думаю, важно отметить, что это не будет компилироваться и дать сообщение "Неисправный вызов" , если код, вызывающий методы дублирования расширений, не находится в том же пространстве имен, что и один из них.
Если OP должно было изменить пространство имен своего класса Blah на test1
или test2
, тогда компиляция кода и расширение в том же пространстве имен, что и вызывающий, - даже если оба пространства имен представлены в usings
. Поэтому, если Blah находится в пространстве имен test1
, возвращается "1", и если Blah находится в пространстве имен test2
, возвращается "2".
Я думаю, что это важно, чтобы добавить к вышеупомянутым ответам, потому что я думаю, что один основной вариант использования - это расширения в локальной библиотеке классов, которые ссылаются на внешние библиотеки расширений (например, разработчики совместно используют общую библиотеку утилиты, но имеют некоторые локальные пользовательские расширения, которые могут не совпадать с тем же именем). Поддерживая настраиваемые локальные расширения в том же пространстве имен, что и код, который их использует, вы можете поддерживать синтаксис вызова внутреннего вызова и не возвращаться к обработке их как вызовы статических методов.
Ответ 2
Никакой метод не будет выбран: вызов неоднозначен и не будет компилироваться.
Почему вы не можете сделать Namespace.ClassNAME.Method()
? Конечно, нет ничего, что помешало бы вам рассматривать методы расширения как обычные статические методы, и на самом деле это единственный способ устранить двусмысленность и скомпилировать программу.
Ответ 3
Как говорит Джон, если оба они существуют, когда вы делаете компиляцию, компиляция просто терпит неудачу.
Но если во время компиляции существует только одна, а затем внешняя библиотека обновляется, чтобы добавить вторую, код, который вы скомпилировали, по-прежнему будет продолжать использовать первый. Это связано с тем, что компилятор превращает ваш код в длинную форму вызова namespace.classname.method.