No C#, a ocultação de nomes ocorre quando um nome declarado em um escopo interno oculta um nome com o mesmo identificador em um escopo externo. Isso pode acontecer em vários cenários, como ao aninhar namespaces, classes e blocos de código, ou ao herdar membros de uma classe base. Neste artigo, exploraremos os dois tipos principais de ocultação de nomes: através de aninhamento e através de herança.
Ocultação de Nomes Através de Aninhamento
A ocultação de nomes através de aninhamento ocorre quando uma entidade em um escopo interno usa o mesmo nome que uma entidade em um escopo externo. Nesse caso, o nome externo é ocultado no escopo interno. Vamos ver um exemplo:
class A
{
int i = 0; // Variável de instância
void F()
{
int i = 1; // Oculta a variável de instância 'i'
void M1()
{
float i = 1.0f; // Oculta a variável 'i' do método F
Func<double, double> dobrar = (double i) => i * 2.0; // Oculta a variável 'i' de M1
}
}
void G()
{
i = 1; // Refere-se à variável de instância 'i'
}
}
Neste exemplo:
- Dentro do método
F
, a variáveli
local oculta a variável de instânciai
. - Dentro da função local
M1
, a variáveli
oculta a variável locali
do métodoF
. - Dentro da expressão lambda, o parâmetro
i
oculta a variáveli
deM1
.
Essa ocultação ocorre porque o C# permite que variáveis locais redefinam variáveis de escopos superiores.
Ocultação de Nomes em Sobrecarga de Métodos
Quando um nome em um escopo interno oculta um nome em um escopo externo, isso afeta todos os métodos sobrecarregados com o mesmo nome. Isso significa que todas as sobrecargas externas ficam inacessíveis no escopo interno.
class Outer
{
static void F(int i) {}
static void F(string s) {}
class Inner
{
static void F(long l) {}
void G()
{
F(1); // Invoca Inner.F (long)
F("Olá"); // Erro: Não há correspondência em Inner
}
}
}
Aqui, a declaração de F(long)
em Inner
oculta todas as sobrecargas de F
em Outer
. Isso causa um erro ao tentar invocar F(string)
.
Ocultação de Nomes Através de Herança
Na herança, a ocultação de nomes ocorre quando uma classe derivada declara membros com o mesmo nome que membros herdados da classe base. Isso pode ocultar constantes, campos, propriedades, eventos, métodos e indexadores herdados.
class Base
{
public void F() {}
}
class Derived : Base
{
public void F() {} // Aviso: oculta o método F da classe base
}
No exemplo acima, o método F
em Derived
oculta o método F
herdado de Base
. Isso gera um aviso no compilador, pois a ocultação de nomes herdados não é um erro, mas pode indicar um comportamento inesperado.
Usando o Modificador new
Para eliminar o aviso e indicar explicitamente que a ocultação de um membro herdado é intencional, você pode usar o modificador new
:
class Base
{
public void F() {}
}
class Derived : Base
{
public new void F() {} // Oculta explicitamente F da classe base
}
O modificador new
informa ao compilador que a ocultação do membro é proposital.
Limitações da Ocultação
A ocultação de nomes herdados é restrita ao escopo da classe que introduz o novo nome. Se o membro oculto for declarado como private
, ele não será acessível em classes derivadas adicionais.
class Base
{
public static void F() {}
}
class Derived : Base
{
private new static void F() {} // Oculta F apenas em Derived
}
class MoreDerived : Derived
{
static void G()
{
F(); // Invoca Base.F, pois F de Derived é privado
}
}
Neste exemplo, o método F
em Derived
oculta F
de Base
, mas como F
é privado em Derived
, a classe MoreDerived
não pode acessar essa versão e, portanto, invoca Base.F
.
Conclusão
A ocultação de nomes em C# é um mecanismo que ocorre tanto por aninhamento quanto por herança. Entender como e quando ocorre a ocultação de nomes é essencial para evitar conflitos de nomes inesperados e garantir que seu código funcione como esperado. Usar o modificador new
pode ajudar a deixar as intenções claras ao lidar com a ocultação através da herança.
Diogo
Posts relacionados
Assine o boletim informativo
* Você receberá as últimas notícias e atualizações sobre suas celebridades favoritas!