Что означает ключевое слово «новый» при использовании внутри интерфейса в C #? - PullRequest
23 голосов
/ 05 июля 2011

Разработка универсального интерфейса Я хотел объявить конструктор в интерфейсе, но там говорится, что конструкторы там запрещены.Тогда я попытался объявить статический метод фабрики, но он говорит, что ни один из статических методов не разрешен, и предлагает использовать ключевое слово «new».Но я почти не представляю, что именно может означать ключевое слово «новый» при использовании внутри интерфейса в C #.Вы?

ОБНОВЛЕНИЕ:

Я не опубликовал ни одного примера кода, потому что не хотел смешивать 2 вопроса - как указать конструктор / фабрику в интерфейсе И что делает«Новое» ключевое слово означает в интерфейсах.Я даже был вынужден указать только первую часть, потому что StackOverflow не принял второй вопрос в чистом виде, заявив, что он не соответствует стандартам качества.

Но, как вам потребуется, я опробую то, что япытался достичь:

Interface IMyInterface <T, U, V>
{
    IMyInterface (T, U, U);
    // OR
    static IMyInterface GetNewIMyInterface (T, U, U);
}

Я просто хочу, чтобы каждый производный класс реализовывал такой конструктор.

Ответы [ 7 ]

56 голосов
/ 05 июля 2011

Ответ Балы правильный, но было бы полезно узнать , почему вы захотите это сделать.Рассмотрим проблему, с которой столкнулись дизайнеры BCL при разработке библиотек для CLR версии 2. Был существующий интерфейс:

interface IEnumerable
{
  IEnumerator GetEnumerator();
}

Теперь вы хотите добавить:

interface IEnumerable<T> : IEnumerable
{
  new IEnumerator<T> GetEnumerator();
}

Новый интерфейс отличается от старого только типом возвращаемого значения.

Каков ваш выбор?

1) Пометьте новый GetEnumerator как «новый», чтобы компилятор знал, что это должно бытьновый метод, который не конфликтует со старым методом с тем же именем, но с другим типом возвращаемого значения.

2) Измените имя на GetEnumerator2.

3) Не наследуйте от исходного IEnumerable.

Варианты 2 и 3 ужасны.Вариант 1 великолепен: новые перечислимые элементы работают без проблем с кодом, который ожидает старые перечислимые значения, но код, написанный для использования новых перечислимых элементов, по умолчанию получает «новое» общее поведение.

26 голосов
/ 05 июля 2011

Ключевое слово new сообщает компилятору, что ваше определение скрывает определение, содержащееся в интерфейсах, которые может расширять ваш интерфейс.

4 голосов
/ 05 июля 2011

Вы не можете указать ни конструктор, ни статический метод в интерфейсе ... что вы можете сделать, это добавить ограничение типа для параметра универсального типа, например

void Foo<T>() where T : new()
{
    T t = new T();
    // Do stuff with t
}

Это то, о чем ты думаешь?

3 голосов
/ 05 июля 2011

Вы используете интерфейс, но, похоже, вам нужен базовый класс. Интерфейс никогда не должен нуждаться в конструкторе, так как он не может содержать полей, которые нужно инициализировать в конструкторе. Я думаю, что вы хотите использовать базовый класс.

3 голосов
/ 05 июля 2011

Интерфейс должен указывать контракт.Он будет содержать только сигнатуры методов и не будет реализован.Интерфейс не может быть создан напрямую, поэтому конструктор не допускается в интерфейсе.

http://msdn.microsoft.com/en-us/library/87d83y5b(v=vs.80).aspx

1 голос
/ 11 июля 2018

Во-первых, единственное, что на самом деле делает ключевое слово 'new', - это подсказывает компилятору НЕ выдавать предупреждение о том, что вы должны использовать ключевое слово 'new'. Помимо удаления предупреждения само ключевое слово ничего не делает (в рассматриваемом контексте).

Теперь компилятор ХОЧЕТ, чтобы вы использовали ключевое слово 'new', когда вы переопределяете элемент (свойство или метод), уже определенный в интерфейсе, от которого вы наследуете, и для этого есть как минимум две возможные причины. Во-первых, как упоминал Эрик Липперт, вы можете захотеть, чтобы метод возвращал другой тип (или определял свойство с тем же именем с другим типом). Другая возможность, если вы хотите определить разные реализации для двух интерфейсов:

interface A
{
    void a();
}

interface B : A
{
    new void a();
}

class C : B
{
    void A.a() { Console.WriteLine("Called by interface A!"); }
    void B.a() { Console.WriteLine("Called by interface B!"); }
}

static class Test
{
    public static void DoTest()
    {
        B b = new C();
        b.a();       // Produces "Called by interface B!"
        ((A)b).a();  // Produces "Called by interface A!"
    }
}

Если вы попытаетесь определить B.a() в C без переопределения a() в B, вы получите предупреждение о том, что он не является членом интерфейса: явное объявление интерфейса требует использования интерфейса, для которого этот член явно определен .

0 голосов
/ 05 июля 2011

C # и .NET не позволяют объявлять конструктор интерфейса.

Это просто обязательное ограничение реализации этого интерфейса (см. ISerializable в библиотеках .NET).

Если вы подумаете об этом, иметь конструктор в интерфейсе не имеет смысла, так как вы должны знать конкретный класс, который вы хотите создать при вызове конструктора. Как бы вы вызвали такой конструктор интерфейса и каков был бы результат?

...