C# - Использование ключевого слова virtual+override по сравнению с новым

typedef typename Tail::inUnion dummy;

Однако я не уверен, что реализация inUnion верна. Если я правильно понимаю, этот класс не должен быть создан, поэтому вкладка «fail» никогда не будет автоматически терпеть неудачу. Возможно, было бы лучше указать, находится ли тип в объединении или нет с простым булевым значением.

template  struct Contains;

template 
struct Contains >
{
    enum { result = Contains::result };
};

template 
struct Contains >
{
    enum { result = true };
};

template 
struct Contains
{
    enum { result = false };
};

PS: Посмотрите на Boost :: Variant

PS2: посмотрите на typelists , особенно в книге Андрея Александреску: Modern C ++ Design

201
задан dbc 11 May 2019 в 20:39
поделиться

7 ответов

"Новое" ключевое слово не переопределяет, оно показывает новый метод, который не имеет никакого отношения к методу базового класса.

public class Foo
{
     public bool DoSomething() { return false; }
}

public class Bar : Foo
{
     public new bool DoSomething() { return true; }
}

public class Test
{
    public static void Main ()
    {
        Foo test = new Bar ();
        Console.WriteLine (test.DoSomething ());
    }
}

Это печатает ложь при использовании переопределения, это распечатало бы верный.

(Основной код, взятый от Joseph Daigle)

Так, при выполнении реального полиморфизма, НЕОБХОДИМО ВСЕГДА ПЕРЕОПРЕДЕЛЯТЬ . Единственное место, где необходимо использовать "новый", - когда метод не связан всегда с версией базового класса.

180
ответ дан Dan Bechard 23 November 2019 в 05:02
поделиться

Я всегда нахожу вещи как это более понятными с изображениями:

Снова, беря joseph код daigle,

public class Foo
{
     public /*virtual*/ bool DoSomething() { return false; }
}

public class Bar : Foo
{
     public /*override or new*/ bool DoSomething() { return true; }
}

, Если Вы тогда называете код как это:

Foo a = new Bar();
a.DoSomething();

ПРИМЕЧАНИЕ: важная вещь состоит в том, что наш объект на самом деле Bar, но мы хранение его в переменной типа Foo (это подобно кастингу его)

Тогда, результат будет следующим образом, в зависимости от того, использовали ли Вы virtual / override или new при объявлении классов.

Virtual/Override explanation image

224
ответ дан Orion Edwards 23 November 2019 в 05:02
поделиться

Вот некоторый код для понимания различия в поведении виртуальных и невиртуальных методов:

class A
{
    public void foo()
    {
        Console.WriteLine("A::foo()");
    }
    public virtual void bar()
    {
        Console.WriteLine("A::bar()");
    }
}

class B : A
{
    public new void foo()
    {
        Console.WriteLine("B::foo()");
    }
    public override void bar()
    {
        Console.WriteLine("B::bar()");
    }
}

class Program
{
    static int Main(string[] args)
    {
        B b = new B();
        A a = b;
        a.foo(); // Prints A::foo
        b.foo(); // Prints B::foo
        a.bar(); // Prints B::bar
        b.bar(); // Prints B::bar
        return 0;
    }
}
42
ответ дан Franci Penov 23 November 2019 в 05:02
поделиться

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

, Например

public class Foo
{
     public bool DoSomething() { return false; }
}

public class Bar : Foo
{
     public new bool DoSomething() { return true; }
}

метод существует на обоих типах. Когда Вы будете использовать отражение и получаете членов типа Bar, Вы на самом деле найдете 2 метода названными DoSomething(), которые смотрят точно то же. При помощи new Вы эффективно скрываете реализацию в базовом классе, так, чтобы, когда классы происходят от Bar (в моем примере) вызов метода base.DoSomething() перешел в Bar а не Foo.

19
ответ дан Joseph Daigle 23 November 2019 в 05:02
поделиться

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

(new SubClass() as BaseClass).VirtualFoo()

будет звонить, SubClass имеет overriden VirtualFoo () метод.

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

(new SubClass() as BaseClass).NewBar()

назовет NewBar BaseClass () методом, тогда как:

(new SubClass()).NewBar()

назовет NewBar SubClass () методом.

9
ответ дан Wedge 23 November 2019 в 05:02
поделиться

Вне просто технических деталей я думаю с помощью виртуального / переопределение передает большую семантическую информацию о дизайне. Когда Вы объявляете виртуальный метод, Вы указываете, что ожидаете, что классы с реализацией могут хотеть обеспечить свои собственные, реализации не по умолчанию. Исключение этого в базовом классе, аналогично, объявляет ожидание, что метод по умолчанию должен быть достаточным для всех классов с реализацией. Точно так же можно использовать абстрактные объявления, чтобы вынудить классы с реализацией обеспечить свою собственную реализацию. Снова, я думаю, что это связывается много о том, как программист ожидает, что код будет использоваться. Если бы я писал и базовые классы и классы с реализацией и использовал новый, то я серьезно заново продумал бы решение не сделать метод виртуальным в родителе и объявить мое намерение конкретно.

8
ответ дан tvanfosson 23 November 2019 в 05:02
поделиться

Различие между ключевым словом переопределения и новым ключевым словом - то, что первый делает переопределение метода, и позже делает сокрытие метода.

Выезд следующие ссылки для получения дополнительной информации...

MSDN и Другой

4
ответ дан Nescio 23 November 2019 в 05:02
поделиться
Другие вопросы по тегам:

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