¿Cuál es el propósito de hidebysig en un método MSIL?
-
19-08-2019 - |
Pregunta
Uso de ildasm y un programa C #, por ejemplo,
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 la construcción hidebysig?
Solución
De ECMA 335 , sección 8.10.4 de la partición 1:
El CTS proporciona control independiente sobre los dos nombres que son visibles de un tipo base (oculto) y el compartir ranuras de diseño en el derivado clase (anulación). Ocultar es controlado marcando un miembro en el clase derivada como ocultar por nombre u ocultar por nombre y firma. Ocultación siempre se realiza en función del tipo de miembro, es decir, campo derivado los nombres pueden ocultar nombres de campo base, pero no nombres de métodos, nombres de propiedades o nombres de eventos Si un miembro derivado es marcado ocultar por nombre, luego miembros de del mismo tipo en la clase base con el mismo nombre no es visible en el clase derivada; si el miembro está marcado ocultar por nombre y firma, entonces solo un miembro del mismo tipo con exactamente el mismo nombre y tipo (para campos) o la firma del método (para métodos) es oculto de la clase derivada. Implementación de la distinción entre estas dos formas de esconderse es proporcionado completamente por el idioma fuente compiladores y la biblioteca de reflexión; no tiene impacto directo en el VES en sí mismo.
(No está claro de inmediato de eso, pero hidebysig
significa "ocultar por nombre y firma").
También en la sección 15.4.2.2 de la partición 2:
hidebysig se suministra para el uso de herramientas y es ignorado por el VES. Eso 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 omite, el método debería ocultar todos los métodos de la misma nombre, independientemente de la firma.
Como ejemplo, suponga 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 Bar (string)
no oculta Bar ()
, porque el compilador de C # usa hidebysig . Si usaba "ocultar por nombre" semántica, no podría llamar a
Bar ()
en absoluto en una referencia de tipo Derivado
, aunque aún podría lanzarlo a Base y llamarlo de esa manera.
EDITAR: acabo de probar esto compilando el código anterior en un archivo DLL, ildamándolo, eliminando hidebysig
para Bar ()
y Bar (string )
, ilasming de nuevo, luego tratando de llamar a Bar ()
desde 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();
(Sin problemas de compilación)
Otros consejos
Según la respuesta de THE SKEET, además, la razón de esto es que Java y C # permiten al cliente de una clase llamar 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. Por lo tanto, 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
, para que se conviertan en parte del " conjunto de sobrecarga " para ese nombre de método.
De acuerdo con Documentos de Microsoft
Cuando un miembro en una clase derivada se declara con el modificador Ccode
new
o el modificadorShadows
de Visual Basic, puede ocultar un miembro del mismo nombre en la clase base. C # oculta los miembros de la clase base por firma. Ese es decir, si el miembro de la clase base tiene múltiples sobrecargas, la única que está oculto es el que tiene la firma idéntica. Por el contrario, Visual Basic oculta todas las sobrecargas de la clase base. Por lo tanto, IsHideBySig devuelvefalse
en un miembro declarado con lasShadows
de Visual Basic modificador ytrue
en un miembro declarado con el modificador Ccodenew
.