2009-03-23 10 views
33

En C# ¿qué significa el término sombreado? He leído this link pero no lo entendí del todo.¿Qué es el sombreado?

+1

¿Cómo está respondiendo a la pregunta de nuevo va a ayudar a entender que? –

+12

No todo el mundo explica las cosas exactamente de la misma manera ¿o sí? ¿No había maestros en la escuela que pensabas que eran mejores que otros? –

+1

Se debe tener en cuenta que el sombreado es un término VB: C# llama a este ocultamiento. –

Respuesta

29
  • Anulación: la redefinición de un método existente en una clase base
  • remedo: la creación de un método completamente nuevo con la misma firma como uno de una clase base
+0

Nuevo método: ¿con la misma firma o? – User

+1

+1 muy bien resumido! – Csharp

+2

Tenga en cuenta que con el sombreado puede cambiar el tipo de devolución. –

3

He aquí un MSDN article de sombreado. Los ejemplos de lenguaje están en Visual Basic (desafortunadamente no hay una página equivalente de C# en MSDN), pero trata generalmente con los conceptos y, con suerte, debería ayudarlo a comprender de todos modos.

Editar: parece que no es un C# article de sombreado, excepto que se llama escondido en C#. Además, this page ofrece una buena visión general.

+0

Esto se debe a que se llama escondido en C#: http://msdn.microsoft.com/en-us/library/aa691133(VS.71).aspx –

+0

Ah, que explicaría. – Noldorin

20

Supongamos que tengo una clase base que implementa un método virtual:

public class A 
{ 
    public virtual void M() { Console.WriteLine("In A.M()."); } 
} 

I también tienen una clase derivada que también define un método M:

public class B : A 
{ 
    // could be either "new" or "override", "new" is default 
    public void M() { Console.WriteLine("In B.M()."); } 
} 

Ahora, supongamos que escribo un programa como este:

A alpha = new B(); // it's really a B but I cast it to an A 
alpha.M(); 

Tengo dos opciones diferentes para la forma en que quiero que se implemente. El comportamiento predeterminado es llamar a la versión A de M. (Esto es idéntico al comportamiento si aplicó la palabra clave "new" al B.M().)

Esto se denomina "sombreado" cuando tenemos un método con el mismo nombre pero un comportamiento diferente cuando se lo llama desde la clase base.

Alternativamente, podríamos haber especificado "override" en B.M(). En este caso, alpha.M() habría llamado la versión B de M.

44

Sombreado oculta un método en una clase base. Usando el ejemplo de la pregunta se conectó:

class A 
{ 
    public int Foo(){ return 5;} 
    public virtual int Bar(){return 5;} 
} 
class B : A 
{ 
    public new int Foo() { return 1;} 
    public override int Bar() {return 1;} 
} 

Clase B anula el método virtual Bar. Es oculta (sombras) el método no virtual Foo. La anulación utiliza la palabra clave que reemplaza la palabra clave. El remedo se realiza con la nueva palabra clave .

En el código anterior, si no se utiliza la palabra clave nueva la hora de definir el método Foo en clase B, se llega a esta advertencia del compilador:

'test.B.Foo()' hides inherited member 'test.A.Foo()'. Use the new keyword if hiding was intended. 
+0

¿Cuál es el propósito funcional de esto? ¿Por qué escondes algo en lugar de anularlo? – sab669

+3

@ sab669: imagine que desea "anular" un método no virtual. En realidad, no puede anularlo, por lo que lo sombrea. No es una solución perfecta porque no actúa como un método virtual anulado en todos los casos, pero cuando se llama desde la clase derivada, funcionará como se esperaba. Es relativamente raro que quieras hacer esto, pero cuando lo necesitas realmente lo necesitas. –

+0

Ah, por lo que solo tipo de existe como un "bien ese método no es virtual, y por una razón u otra, no puede hacer que sea virtual, tan nuevo tendrá que hacer" tipo de cosas? – sab669

-3

remedo no es algo que yo' Preocuparse por comprender o implementar a menos que "encaje" con el problema realmente bien.Lo he visto usar incorrectamente y causar extraños errores de lógica mucho más a menudo que ser usado correctamente. La gran causa, creo, es cuando el programador olvida poner anulaciones en una firma de método, entonces la advertencia del compilador sugerirá la nueva palabra clave. Siempre he sentido que debería recomendar el uso de la anulación.

+0

Esto se siente como un comentario. – Neolisk

10

Sombrear consiste en ocultar un método de clase base con una nueva definición en una clase secundaria.

La diferencia entre ocultar y sobrescribir tiene que ver con la forma en que se invocan los métodos.

De esta forma, cuando se anula un método virtual, la dirección de llamada para la tabla de llamadas a métodos de la clase base se reemplaza por la dirección de la rutina secundaria.

Por otro lado, cuando se oculta un método, se agrega una nueva dirección a la tabla de llamadas al método de la clase secundaria.

Cuando se realiza una llamada al método en cuestión:

  1. Se obtiene el tipo de clase tabla de llamadas de método, si estamos invocando con una referencia a la clase base se obtiene a continuación la tabla de métodos de la clase base, si tenemos una referencia a la clase hija, entonces se obtiene la tabla del método de la clase hija.
  2. El método se busca en la tabla, si se encuentra, la invocación tiene lugar, de lo contrario, se busca en la tabla de métodos de la clase base.

Si invocamos el método con una referencia a la clase secundaria, el comportamiento es el mismo, si el método ha sido reemplazado, la dirección del método se encontrará en la clase base, si el método fue ocultado, el método la dirección se encontrará en la clase secundaria y, como ya se encontró, no se buscará en la tabla de la clase base.

Si invocamos el método con una referencia a la clase base, el comportamiento cambia. Al anular, como la dirección del método sobrescribe la entrada de la clase base, llamaremos al método secundario, incluso cuando se mantiene una referencia a la clase base. Con el sombreado, la tabla de métodos de la clase base (que es la única visible al mantener una referencia a la clase base) contiene la dirección del método virtual y, por lo tanto, se llamará al método de la clase base.

En general, el sombreado es una mala idea, ya que introduce una diferencia en el comportamiento de una instancia según la referencia que tengamos.

8

Ampliando respuesta correcta de Kent

Al eliminar la ambigüedad cuando el método que se llamará, me gusta pensar en sombreado vs. anulando con la siguiente

  • remedo: El método llamado depende del tipo de la referencia en el punto donde se realiza la llamada
  • Anulación: El método llamado depende del tipo de objeto en el punto donde se realiza la llamada.
-4
private static int x = 10; 


static void Main(string[] args) 
    { int x = 20; 
     if (Program.x == 10) 
     { 
      Console.WriteLine(Program.x); 
     } 
     Console.WriteLine(x);} 

Salida:

+1

Esto no responde la pregunta – alu

2

Si desea ocultar método de la clase base, utilizar Ignorar en la base [método virtual en la base]

si desea ocultar Método de clase infantil, Usar nuevo en la base [método no virtual en la base] -> sombra

Base B=new Child() 

B.VirtualMethod() -> llamadas a métodos de Child-Pugh

B.NonVirtualMethod() -> Llamadas método de la clase base

Cuestiones relacionadas