Curiosidades C# – Modificador ‘new’ (Member Shadowing)

Quando usada como um modificador de declaração, a palavra-chave ‘new‘ oculta explicitamente um membro herdado de uma classe base. Este é um recurso do C# que é o oposto lógico de fazer um ‘overriding‘, e pode ser denominado ‘shadowing‘.

Se uma classe derivada define um membro que é idêntico a um membro definido em uma classe base, a classe derivada ‘apaga’ a versão do pai. No mundo real, a possibilidade de isso ocorrer é maior quando você está criando uma subclasse de uma classe que você não criou ou não tem acesso.

Imagine por exemplo que existe uma classe de terceiros, chamada Shape

    public class Shape
    {
        public int Code { get; set; }

        public void PrintShapeArea()
        {
            Console.WriteLine("Call Shape.PrintShapeArea");
        }
    }

Você tem quem implementar uma classe que é to tipo Shape, chamada Circle. Então podemos fazer da seguinte maneira.

    public class Circle : Shape
    {
        public void PrintShapeArea()
        {
            Console.WriteLine("Call Circle.PrintShapeArea");
        }
    }

Quando for compilado esse código vai gerar um aviso:

‘Circle.PrintShapeArea()’ hides inherited member ‘Shape.PrintShapeArea()’. Use the new keyword if hiding was intended.

O problema é que você tem uma classe derivada Circle que contém um método idêntico a um método herdado. Para resolver esse problema, você tem algumas opções. Você pode simplesmente alterar o método PrintShapeArea() adicionando a palavra-chave override. Com esta abordagem, o tipo Circle é capaz de estender o comportamento padrão da classe base conforme necessário. No entanto, neste exemplo não temos acesso à classe base por se tratar de uma biblioteca de terceiros e por isso não teríamos como colocar o método pai como virtual.

Como alternativa, você pode incluir a palavra-chave new no método PrintShapeArea() da classe Circle. Isso afirma explicitamente que a implementação do tipo derivado é intencionalmente projetada para ignorar efetivamente a versão do pai.

    public class Circle : Shape
    {
        public new void PrintShapeArea()
        {
            Console.WriteLine("Call Circle.PrintShapeArea");
        }
    }

E com isso não temos mais o aviso do compilador.

Você também pode aplicar a palavra-chave new a qualquer tipo de membro herdado de uma classe base (campo, constante, membro estático ou propriedade). Como outro exemplo, suponha que Circle deseja ocultar a propriedade Code que foi herdada.

    public class Circle : Shape
    {
        public new int Code { get; set; }

        public new void PrintShapeArea()
        {
            Console.WriteLine("Call Circle.PrintShapeArea");
        }
    }

Realizar uma chamada ao método ocultado

Claro que ainda podemos chamar o método da classe base fazendo um cast explícito como no exemplo abaixo.

    class Program
    {
        static void Main(string[] args)
        {
            Circle circle = new Circle();
            circle.PrintShapeArea();

            ((Shape)circle).PrintShapeArea();
        }
    }
    //Call Circle.PrintShapeArea
    //Call Shape.PrintShapeArea

Qualquer dúvida ou dicas, entre em contato: leandrolt@gmail.com

Principais referências

– https://docs.microsoft.com/pt-br/dotnet/csharp/language-reference/keywords/new-modifier
– Livro: Pro C# 7: With .NET and .NET Core – Andrew Troelsen

Leave a Reply

Your email address will not be published. Required fields are marked *