Controle de versão com as palavras-chave override e new (Guia de Programação em C#)Versioning with the Override and New Keywords (C# Programming Guide)

A linguagem C# foi projetada para que o controle de versão entre classes derivadas e base em diferentes bibliotecas possa evoluir e manter a compatibilidade com versões anteriores.The C# language is designed so that versioning between base and derived classes in different libraries can evolve and maintain backward compatibility. Isso significa, por exemplo, que a introdução de um novo membro em uma classe base com o mesmo nome que um membro em uma classe derivada tem suporte completo pelo C# e não leva a comportamento inesperado.This means, for example, that the introduction of a new member in a base class with the same name as a member in a derived class is completely supported by C# and does not lead to unexpected behavior. Isso também significa que uma classe deve declarar explicitamente se um método destina-se a substituir um método herdado ou se um método é um novo método que oculta um método herdado de nome semelhante.It also means that a class must explicitly state whether a method is intended to override an inherited method, or whether a method is a new method that hides a similarly named inherited method.

No C#, as classes derivadas podem conter métodos com o mesmo nome que os métodos da classe base.In C#, derived classes can contain methods with the same name as base class methods.

  • O método de classe base deve ser definido como virtual.The base class method must be defined virtual.

  • Se o método na classe derivada não for precedido pelas palavras-chave new ou override, o compilador emitirá um aviso e o método se comportará como se a palavra-chave new estivesse presente.If the method in the derived class is not preceded by new or override keywords, the compiler will issue a warning and the method will behave as if the new keyword were present.

  • Se o método na classe derivada for precedido pela palavra-chave new, o método será definido como sendo independente do método na classe base.If the method in the derived class is preceded with the new keyword, the method is defined as being independent of the method in the base class.

  • Se o método na classe derivada for precedido pela palavra-chave override, os objetos da classe derivada chamarão esse método em vez do método da classe base.If the method in the derived class is preceded with the override keyword, objects of the derived class will call that method instead of the base class method.

  • O método da classe base pode ser chamado de dentro da classe derivada usando a palavra-chave base.The base class method can be called from within the derived class using the base keyword.

  • As palavras-chave override, virtual e new também podem ser aplicadas a propriedades, indexadores e eventos.The override, virtual, and new keywords can also be applied to properties, indexers, and events.

Por padrão, os métodos C# não são virtuais.By default, C# methods are not virtual. Se um método for declarado como virtual, qualquer classe que herdar o método pode implementar sua própria versão.If a method is declared as virtual, any class inheriting the method can implement its own version. Para tornar um método virtual, o modificador virtual é usado na declaração de método da classe base.To make a method virtual, the virtual modifier is used in the method declaration of the base class. A classe derivada pode, em seguida, substituir o método virtual base usando a palavra-chave override ou ocultar o método virtual na classe base usando a palavra-chave new.The derived class can then override the base virtual method by using the override keyword or hide the virtual method in the base class by using the new keyword. Se nem a palavra-chave override nem a new for especificada, o compilador emitirá um aviso e o método na classe derivada ocultará o método na classe base.If neither the override keyword nor the new keyword is specified, the compiler will issue a warning and the method in the derived class will hide the method in the base class.

Para demonstrar isso na prática, suponha por um momento que a Empresa A tenha criado uma classe chamada GraphicsClass, que seu programa usa.To demonstrate this in practice, assume for a moment that Company A has created a class named GraphicsClass, which your program uses. A seguir está GraphicsClass:The following is 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:Your company uses this class, and you use it to derive your own class, adding a new method:

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

Seu aplicativo é usado sem problemas, até a Empresa A lançar uma nova versão de GraphicsClass, que se parece com o seguinte código:Your application is used without problems, until Company A releases a new version of GraphicsClass, which resembles the following code:

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

A nova versão de GraphicsClass agora contém um método chamado DrawRectangle.The new version of GraphicsClass now contains a method named DrawRectangle. Inicialmente, nada ocorre.Initially, nothing occurs. A nova versão ainda é compatível em relação ao binário com a versão antiga.The new version is still binary compatible with the old version. Qualquer software que você implantou continuará a funcionar, mesmo se a nova classe for instalada nesses sistemas de computador.Any software that you have deployed will continue to work, even if the new class is installed on those computer systems. Todas as chamadas existentes para o método DrawRectangle continuarão a fazer referência à sua versão, em sua classe derivada.Any existing calls to the method DrawRectangle will continue to reference your version, in your derived class.

No entanto, assim que você recompilar seu aplicativo usando a nova versão do GraphicsClass, você receberá um aviso do compilador, CS0108.However, as soon as you recompile your application by using the new version of GraphicsClass, you will receive a warning from the compiler, CS0108. Este aviso informa que você deve considerar como deseja que seu método DrawRectangle se comporte em seu aplicativo.This warning informs you that you have to consider how you want your DrawRectangle method to behave in your application.

Se desejar que seu método substitua o novo método de classe base, use a palavra-chave override:If you want your method to override the new base class method, use the override keyword:

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

A palavra-chave override garante que todos os objetos derivados de YourDerivedGraphicsClass usarão a versão da classe derivada de DrawRectangle.The override keyword makes sure that any objects derived from YourDerivedGraphicsClass will use the derived class version of DrawRectangle. Os objetos derivados de YourDerivedGraphicsClass ainda poderão acessar a versão da classe base de DrawRectangle usando a palavra-chave base:Objects derived from YourDerivedGraphicsClass can still access the base class version of DrawRectangle by using the base keyword:

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.If you do not want your method to override the new base class method, the following considerations apply. Para evitar confusão entre os dois métodos, você pode renomear seu método.To avoid confusion between the two methods, you can rename your method. Isso pode ser demorado e propenso a erros e simplesmente não ser prático em alguns casos.This can be time-consuming and error-prone, and just not practical in some cases. No entanto, se seu projeto for relativamente pequeno, você poderá usar opções de Refatoração do Visual Studio para renomear o método.However, if your project is relatively small, you can use Visual Studio's Refactoring options to rename the method. Para obter mais informações, consulte Refatorando classes e tipos (Designer de Classe).For more information, see Refactoring Classes and Types (Class Designer).

Como alternativa, você pode evitar o aviso usando a palavra-chave new na definição da classe derivada:Alternatively, you can prevent the warning by using the keyword new in your derived class definition:

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

Usando a palavra-chave new informa ao compilador que sua definição oculta a definição que está contida na classe base.Using the new keyword tells the compiler that your definition hides the definition that is contained in the base class. Este é o comportamento padrão.This is the default behavior.

Seleção de método e substituiçãoOverride and Method Selection

Quando um método é chamado em uma classe, o compilador C# seleciona o melhor método a ser chamado 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.When a method is named on a class, the C# compiler selects the best method to call if more than one method is compatible with the call, such as when there are two methods with the same name, and parameters that are compatible with the parameter passed. Os métodos a seguir seriam compatíveis:The following methods would be compatible:

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# tenta primeiro tornar a chamada compatível com as versões do DoWork originalmente declarado em Derived.When DoWork is called on an instance of Derived, the C# compiler will first try to make the call compatible with the versions of DoWork declared originally on 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.Override methods are not considered as declared on a class, they are new implementations of a method declared on a base class. 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 com o mesmo nome e parâmetros compatíveis.Only if the C# compiler cannot match the method call to an original method on Derived will it try to match the call to an overridden method with the same name and compatible parameters. Por exemplo:For example:

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

Como a variável val pode ser convertida para um duplo implicitamente, o compilador C# chama DoWork(double) em vez de DoWork(int).Because the variable val can be converted to a double implicitly, the C# compiler calls DoWork(double) instead of DoWork(int). Há duas formas de evitar isso.There are two ways to avoid this. Primeiro, evite declarar novos métodos com o mesmo nome que os métodos virtuais.First, avoid declaring new methods with the same name as virtual methods. Segundo, você pode instruir o compilador C# para chamar o método virtual fazendo-o pesquisar a lista do método de classe base convertendo a instância do Derived para Base.Second, you can instruct the C# compiler to call the virtual method by making it search the base class method list by casting the instance of Derived to Base. Como o método é virtual, a implementação de DoWork(int) em Derived será chamada.Because the method is virtual, the implementation of DoWork(int) on Derived will be called. Por exemplo:For example:

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

Para obter mais exemplos de new e override, consulte Quando usar as palavras-chave override e new.For more examples of new and override, see Knowing When to Use Override and New Keywords.

Consulte tambémSee also