Partilhar via


Controle de versão com a substituição e novas palavras-chave (Guia de Programação em C#)

A linguagem C# foi projetada para que o controle de versão entre classes base e derivadas em bibliotecas diferentes possa evoluir e manter a compatibilidade com versões anteriores. Isso significa, por exemplo, que a introdução de um novo membro em uma classe base com o mesmo nome de um membro em uma classe derivada é completamente suportada pelo C# e não leva a um comportamento inesperado. Isso também significa que uma classe deve declarar explicitamente se um método se destina a substituir um método herdado ou se um método é um novo método que oculta um método herdado com nome semelhante.

Em C#, as classes derivadas podem conter métodos com o mesmo nome que os métodos de classe base.

  • Se o método na classe derivada não for precedido por palavras-chave novas ou de substituição , o compilador emitirá um aviso e o método se comportará como se a new palavra-chave estivesse presente.

  • Se o método na classe derivada é precedido com a new palavra-chave, o método é definido como sendo independente do método na classe base.

  • Se o método na classe derivada for precedido com a override palavra-chave, os objetos da classe derivada chamarão esse método em vez do método de classe base.

  • Para aplicar a override palavra-chave ao método na classe derivada, o método de classe base deve ser definido virtual.

  • O método de classe base pode ser chamado de dentro da classe derivada usando a base palavra-chave.

  • O override, virtuale new as palavras-chave também podem ser aplicadas a propriedades, indexadores e eventos.

Por padrão, os métodos C# não são virtuais. Se um método for declarado como virtual, qualquer classe que herde o método poderá implementar sua própria versão. Para tornar um método virtual, o virtual modificador é usado na declaração de método da classe base. A classe derivada pode então substituir o método virtual base usando a override palavra-chave ou ocultar o método virtual na classe base usando a new palavra-chave. Se nem a override palavra-chave nem a new palavra-chave forem especificadas, o compilador emitirá um aviso e o método na classe derivada ocultará o método na classe base.

Para demonstrar isso na prática, assuma por um momento que a Empresa A criou uma classe chamada GraphicsClass, que seu programa usa. O seguinte é GraphicsClass:

class GraphicsClass
{
    public virtual void DrawLine() { }
    public virtual void DrawPoint() { }
}

Sua empresa usa essa classe, e você a usa para derivar sua própria classe, adicionando um novo método:

class YourDerivedGraphicsClass : GraphicsClass
{
    public void DrawRectangle() { }
}

Seu aplicativo é usado sem problemas, até que a empresa A libere uma nova versão do GraphicsClass, que se assemelha ao seguinte código:

class GraphicsClass
{
    public virtual void DrawLine() { }
    public virtual void DrawPoint() { }
    public virtual void DrawRectangle() { }
}

A nova versão do GraphicsClass agora contém um método chamado DrawRectangle. Inicialmente, nada ocorre. A nova versão ainda é binária compatível com a versão antiga. Qualquer software que você tenha implantado continuará a funcionar, mesmo que a nova classe esteja instalada nesses sistemas de computador. Quaisquer chamadas existentes para o método DrawRectangle continuarão a fazer referência à sua versão, na sua classe derivada.

No entanto, assim que você recompilar seu aplicativo usando a nova versão do GraphicsClass, você receberá um aviso do compilador, CS0108. Este aviso informa-o de que tem de considerar como pretende que o seu DrawRectangle método se comporte na sua aplicação.

Se você quiser que seu método substitua o novo método de classe base, use a override palavra-chave:

class YourDerivedGraphicsClass : GraphicsClass
{
    public override void DrawRectangle() { }
}

A override palavra-chave garante que todos os objetos derivados usarão a versão de YourDerivedGraphicsClass classe derivada do DrawRectangle. Os objetos derivados de YourDerivedGraphicsClass ainda podem acessar a versão da classe base usando DrawRectangle a palavra-chave base:

base.DrawRectangle();

Se você não quiser que seu método substitua o novo método de classe base, as seguintes considerações se aplicam. Para evitar confusão entre os dois métodos, você pode renomear seu método. Isso pode ser demorado e propenso a erros, e simplesmente não é prático em alguns casos. No entanto, se seu projeto for relativamente pequeno, você pode usar as opções de refatoração do Visual Studio para renomear o método. Para obter mais informações, consulte Refatoração de classes e tipos (Class Designer).

Como alternativa, você pode evitar o aviso usando a palavra-chave new em sua definição de classe derivada:

class YourDerivedGraphicsClass : GraphicsClass
{
    public new void DrawRectangle() { }
}

O uso da new palavra-chave informa ao compilador que sua definição oculta a definição contida na classe base. Este é o comportamento predefinido.

Substituição e seleção de método

Quando um método é nomeado em uma classe, o compilador C# seleciona o melhor método para chamar se mais de um método for compatível com a chamada, como quando há dois métodos com o mesmo nome e parâmetros que são compatíveis com o parâmetro passado. Os seguintes métodos seriam compatíveis:

public class Derived : Base
{
    public override void DoWork(int param) { }
    public void DoWork(double param) { }
}

Quando DoWork é chamado em uma instância do Derived, o compilador C# primeiro tentará tornar a chamada compatível com as versões do declarado DoWork originalmente em Derived. Os métodos de substituição não são considerados como declarados em uma classe, eles são novas implementações de um método declarado em uma classe base. Somente se o compilador C# não puder corresponder a chamada de método a um método original no Derived, ele tentará corresponder a chamada a um método substituído com o mesmo nome e parâmetros compatíveis. Por exemplo:

int val = 5;
Derived d = new Derived();
d.DoWork(val);  // Calls DoWork(double).

Como a variável val pode ser convertida em um duplo implicitamente, o compilador C# chama DoWork(double) em vez de DoWork(int). Há duas maneiras de evitar isso. Primeiro, evite declarar novos métodos com o mesmo nome dos métodos virtuais. Em segundo lugar, você pode instruir o compilador C# a chamar o método virtual fazendo com que ele pesquise a lista de métodos de classe base convertendo a instância de Derived para Base. Como o método é virtual, a implementação do DoWork(int) on Derived será chamada. Por exemplo:

((Base)d).DoWork(val);  // Calls DoWork(int) on Derived.

Para obter mais exemplos de new e , consulte Saber quando usar a substituição e novas palavras-chaveoverride.

Consulte também