Diferença entre new e override

Quer saber qual é a diferença entre o seguinte:

Caso 1: Classe Base

public void DoIt(); 

Caso 1: class herdada

 public new void DoIt(); 

Caso 2: Classe Base

 public virtual void DoIt(); 

Caso 2: class herdada

 public override void DoIt(); 

Ambos os casos 1 e 2 parecem ter o mesmo efeito com base nos testes que executei. Existe uma diferença ou uma maneira preferida?

    O modificador de substituição pode ser usado em methods virtuais e deve ser usado em methods abstratos. Isso indica para o compilador usar a última implementação definida de um método. Mesmo se o método for chamado em uma referência à class base, ele usará a implementação substituindo-a.

     public class Base { public virtual void DoIt() { } } public class Derived : Base { public override void DoIt() { } } Base b = new Derived(); b.DoIt(); // Calls Derived.DoIt 

    irá chamar Derived.DoIt se isso replace Base.DoIt .

    O novo modificador instrui o compilador a usar sua implementação de class filho em vez da implementação da class pai. Qualquer código que não esteja referenciando sua class, mas a class pai usará a implementação da class pai.

     public class Base { public virtual void DoIt() { } } public class Derived : Base { public new void DoIt() { } } Base b = new Derived(); Derived d = new Derived(); b.DoIt(); // Calls Base.DoIt d.DoIt(); // Calls Derived.DoIt 

    Primeiro, chamará Base.DoIt , em seguida, Derived.DoIt . Eles são efetivamente dois methods totalmente separados que, por acaso, têm o mesmo nome, em vez do método derivado que substitui o método base.

    Fonte: blog da Microsoft

    virtual : indica que um método pode ser substituído por um herdeiro

    override : substitui a funcionalidade de um método virtual em uma class base, fornecendo funcionalidade diferente.

    novo : oculta o método original (que não precisa ser virtual), fornecendo funcionalidade diferente. Isso só deve ser usado quando for absolutamente necessário.

    Quando você oculta um método, ainda é possível acessar o método original subindo para a class base. Isso é útil em alguns cenários, mas é perigoso.

    No primeiro caso, você está ocultando a definição na class pai. Isso significa que ele só será invocado quando você estiver lidando com o object como a class filha. Se você converter a class para seu tipo pai, o método do pai será invocado. Na segunda instância, o método é substituído e será chamado independentemente de o object ser convertido como a class pai ou filho.

    tente seguir: (case1)

     ((BaseClass)(new InheritedClass())).DoIt() 

    Editar: virtual + replace são resolvidos em tempo de execução (assim replace realmente sobrescreve methods virtuais), enquanto novo apenas criar novo método com o mesmo nome e oculta o antigo, é resolvido em tempo de compilation -> seu compilador chamará o método it ‘ vê

    No caso 1, se você usou chamar o método DoIt () da class herdada, enquanto o tipo é declarado como a class base, você verá a ação da class base mesmo.

     /* Results Class1 Base1 Class2 Class2 */ public abstract class Base1 { public void DoIt() { Console.WriteLine("Base1"); } } public class Class1 : Base1 { public new void DoIt() { Console.WriteLine("Class1"); } } public abstract class Base2 { public virtual void DoIt() { Console.WriteLine("Base2"); } } public class Class2 : Base2 { public override void DoIt() { Console.WriteLine("Class2"); } } static void Main(string[] args) { var c1 = new Class1(); c1.DoIt(); ((Base1)c1).DoIt(); var c2 = new Class2(); c2.DoIt(); ((Base2)c2).DoIt(); Console.Read(); } 

    A diferença entre os dois casos é que no caso 1, o método base DoIt não é substituído, apenas oculto. O que isto significa é que dependendo do tipo da variável depende de qual método será chamado. Por exemplo:

     BaseClass instance1 = new SubClass(); instance1.DoIt(); // Calls base class DoIt method SubClass instance2 = new SubClass(); instance2.DoIt(); // Calls sub class DoIt method 

    Isso pode ser realmente confuso e resulta em um comportamento não esperado e deve ser evitado, se possível. Então a maneira preferida seria o caso 2.

    Minha maneira de ter em mente as duas palavras-chave que elas são opostas uma da outra.

    override : virtual palavra-chave virtual deve ser definida para replace o método. O método que utiliza a palavra-chave override independentemente do tipo de referência (referência da class base ou class derivada), se for instanciado com a class base, é executado o método da class base. Caso contrário, o método da class derivada será executado.

    new : se a palavra-chave for usada por um método, ao contrário da palavra-chave override , o tipo de referência é importante. Se for instanciado com a class derivada e o tipo de referência for class base, o método da class base será executado. Se ele é instanciado com class derivada e o tipo de referência é class derivada, o método da class derivada é executado. Ou seja, é o contraste da palavra-chave override . Se você esquecer ou omitir para adicionar uma nova palavra-chave ao método, o compilador se comportará por padrão quando uma new palavra-chave for usada.

     class A { public string Foo() { return "A"; } public virtual string Test() { return "base test"; } } class B: A { public new string Foo() { return "B"; } } class C: B { public string Foo() { return "C"; } public override string Test() { return "derived test"; } } 

    Ligue para o main:

     A AClass = new B(); Console.WriteLine(AClass.Foo()); B BClass = new B(); Console.WriteLine(BClass.Foo()); B BClassWithC = new C(); Console.WriteLine(BClassWithC.Foo()); Console.WriteLine(AClass.Test()); Console.WriteLine(BClassWithC.Test()); 

    Saída:

     A B B base test derived test 

    Se a override palavra-chave for usada na class derivada, ela replaceá o método pai.

    Se a palavra-chave new for usada na class derivada, deduza o método hided pelo método pai.

    O artigo abaixo está em vb.net, mas acho que a explicação sobre o novo vs substituições é muito fácil de entender.

    https://www.codeproject.com/articles/17477/the-dark-shadow-of-overrides

    Em algum momento no artigo, há esta frase:

    Em geral, o Shadows assume que a function associada ao tipo é invocada, enquanto que o Overrides assume que a implementação do object é executada.

    A resposta aceita para essa pergunta é perfeita, mas acho que este artigo fornece bons exemplos para adicionar um melhor significado sobre as diferenças entre essas duas palavras-chave.

    Fora de tudo isso, o novo é o mais confuso. Por meio da experimentação, a nova palavra-chave é como dar aos desenvolvedores a opção de replace a implementação da class herdada pela implementação da class base, definindo explicitamente o tipo. É como pensar o contrário.

    No exemplo abaixo, o resultado retornará “Resultado derivado” até que o tipo seja explicitamente definido como Teste BaseClass, somente depois “Resultado base” será retornado.

     class Program { static void Main(string[] args) { var test = new DerivedClass(); var result = test.DoSomething(); } } class BaseClass { public virtual string DoSomething() { return "Base result"; } } class DerivedClass : BaseClass { public new string DoSomething() { return "Derived result"; } } 

    A diferença funcional não será mostrada nestes testes:

     BaseClass bc = new BaseClass(); bc.DoIt(); DerivedClass dc = new DerivedClass(); dc.ShowIt(); 

    Neste exemplo, o Doit que é chamado é aquele que você espera ser chamado.

    Para ver a diferença, você precisa fazer isso:

     BaseClass obj = new DerivedClass(); obj.DoIt(); 

    Você verá se você executou esse teste que no caso 1 (como você definiu), o DoIt() em BaseClass é chamado, no caso 2 (como você definiu), o DoIt() em DerivedClass é chamado.

    Eu tive a mesma pergunta e é realmente confuso, você deve considerar que replace e novas palavras-chave trabalhando apenas com objects do tipo class base e valor da class derivada. Neste caso, somente você verá o efeito de override e new: Então, se você tem as class A e B , B herda de A , então você instancia um object como este:

     A a = new B(); 

    Agora, ao chamar methods, o estado será levado em consideração. Override : significa que ele estende a function do método e, em seguida, usa o método na class derivada, enquanto new informa ao compilador para ocultar o método na class derivada e usar o método na class base. Aqui está uma visão muito boa para esse assunto:

    https://msdn.microsoft.com/EN-US/library/ms173153%28v=VS.140,d=hv.2%29.aspx?f=255&MSPPError=-2147217396

    No primeiro caso, ele chamará o método DoIt () da class derivada, porque new keyword oculta o método DoIt () da class base.

    No segundo caso, será chamado de DoIt ()

      public class A { public virtual void DoIt() { Console.WriteLine("A::DoIt()"); } } public class B : A { new public void DoIt() { Console.WriteLine("B::DoIt()"); } } public class C : A { public override void DoIt() { Console.WriteLine("C::DoIt()"); } } 

    vamos criar uma instância dessas classs

      A instanceA = new A(); B instanceB = new B(); C instanceC = new C(); instanceA.DoIt(); //A::DoIt() instanceB.DoIt(); //B::DoIt() instanceC.DoIt(); //B::DoIt() 

    Tudo é esperado acima. Vamos definir instanceB e instanceC como instanceA e chamar o método DoIt () e verificar o resultado.

      instanceA = instanceB; instanceA.DoIt(); //A::DoIt() calls DoIt method in class A instanceA = instanceC; instanceA.DoIt();//C::DoIt() calls DoIt method in class C because it was overriden in class C