2009-03-17 15 views
78

Usando ildasm y un programa de C#, p.¿Cuál es el propósito de hidebysig en un método MSIL?

static void Main(string[] args) 
{ 

} 

da:

.method private hidebysig static void Main(string[] args) cil managed 
{ 
    .entrypoint 
    // Code size  2 (0x2) 
    .maxstack 8 
    IL_0000: nop 
    IL_0001: ret 
} // end of method Program::Main 

¿Qué hace el constructo hidebysig?

Respuesta

145

De ECMA 335, la sección 8.10.4 de la partición 1:

El CTS proporciona un control independiente sobre ambos los nombres que son visibles de un tipo de base (ocultación) y la de intercambio de intervalos de disposición en la clase derivada (anulación). Ocultar es controlado marcando un miembro en la clase derivada como ocultar por nombre u ocultar por nombre y firma. Ocultar siempre se realiza según el tipo del miembro, es decir, los nombres de los campos derivados pueden ocultar los nombres de los campos base, pero no nombres de métodos, nombres de propiedades o nombres de eventos. Si un miembro derivado es marcado hide por nombre, los miembros de del mismo tipo en la clase base con del mismo nombre no son visibles en la clase derivada; si el miembro está marcada ocultar el nombre y la firma entonces sólo un miembro de la misma clase con exactamente el mismo nombre y tipo (por campos) o firma del método (para los métodos) es oculto a la clase derivada. La implementación de la distinción entre estas dos formas de ocultación es proporcionada en su totalidad por compiladores del lenguaje fuente y la biblioteca de reflexión; no tiene un impacto directo en el VES .

(No es inmediatamente claro de eso, pero hidebysig medios "ocultar por su nombre-y-firma".)

También en la sección 15.4.2.2 de la partición 2:

hidebysig es suministrado para el uso de herramientas y es ignorado por el VES. Es especifica que el método declarado oculta todos los métodos de la clase base tipos que tienen un método coincidente firma; cuando se omita, el método debe ocultar todos los métodos del mismo nombre , independientemente de la firma.

A modo de ejemplo, supongamos que tiene:

public class Base 
{ 
    public void Bar() 
    { 
    } 
} 

public class Derived : Base 
{ 
    public void Bar(string x) 
    { 
    } 
} 

... 

Derived d = new Derived(); 
d.Bar(); 

Eso es válido, porque no lo hace Bar(string) ocultar Bar(), debido a que el compilador de C# utiliza hidebysig. Si utilizaba la semántica de "ocultar por nombre", no podría llamar al Bar() en absoluto en una referencia de tipo Derived, aunque aún podría transmitirlo a Base y llamarlo de esa manera.

EDIT: He intentado esta compilando el código anterior para una DLL, ildasming, eliminando hidebysig para Bar() y Bar(string), ilasming de nuevo, a continuación, tratando de llamar Bar() de otro código:

Derived d = new Derived(); 
d.Bar(); 

Test.cs(6,9): error CS1501: No overload for method 'Bar' takes '0' arguments 
Sin embargo

:

Base d = new Derived(); 
d.Bar(); 

(No hay problemas de compilación.)

+2

En [resumen] (http://stackoverflow.com/a/4760614/256431 "Sombras vs sobrecargas en VB.NET"), es la diferencia entre 'Sombras' y' Sobrecargas' en VB.NET. –

14

de acuerdo con la respuesta del skeet, Además, la razón de esto es que Java y C# permiten que el cliente de una clase llame a cualquier método con el mismo nombre, incluidos los de las clases base. Mientras que C++ no lo hace: si la clase derivada define incluso un único método con el mismo nombre que un método en la clase base, entonces el cliente no puede llamar directamente al método de la clase base, incluso si no toma los mismos argumentos. Entonces, la función se incluyó en CIL para admitir ambos enfoques de sobrecarga.

En C++ puede importar efectivamente un conjunto de sobrecargas con nombre de la clase base con una directiva using, de modo que se vuelvan parte del "conjunto de sobrecarga" para ese nombre de método.

Cuestiones relacionadas