¿Cuál es el propósito de hidebysig en un método MSIL?

92

Usando 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?

rbrayb
fuente

Respuestas:

156

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

El CTS proporciona control independiente sobre los nombres que son visibles desde un tipo base (ocultación) y el intercambio de espacios de diseño en la clase derivada (anulación). La ocultación se controla marcando un miembro en la clase derivada como ocultar por nombre u ocultar por nombre y firma. La ocultación siempre se realiza en función del tipo de miembro, es decir, los nombres de campo derivados pueden ocultar nombres de campos base, pero no nombres de métodos, nombres de propiedades o nombres de eventos. Si un miembro derivado está marcado como oculto por nombre, los miembros del mismo tipo en la clase base con el mismo nombre no son visibles en la clase derivada; si el miembro está marcado como ocultar por nombre y firma, entonces solo un miembro del mismo tipo con exactamente el mismo nombre y tipo (para campos) o firma de método (para métodos) se oculta de la clase derivada. La implementación de la distinción entre estas dos formas de ocultación la proporcionan en su totalidad los compiladores del lenguaje fuente y la biblioteca de reflexión; no tiene un impacto directo en el VES en sí.

(No queda claro de inmediato, pero hidebysigsignifica "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 el VES lo ignora. Especifica que el método declarado oculta todos los métodos de los tipos de clase base que tienen una firma de método coincidente; cuando se omite, el método debe ocultar todos los métodos con el mismo 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 se oculta Bar(), porque el compilador de C # usa hidebysig. Si usara la semántica "ocultar por nombre", no podría llamar Bar()en absoluto a una referencia de tipo Derived, aunque aún podría lanzarla a Base y llamarla de esa manera.

EDIT: He intentado esta compilando el código anterior para una DLL, ildasming, eliminando hidebysigpara Bar()y Bar(string), ilasming de nuevo, a continuación, tratando de llamar Bar()a 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).

Jon Skeet
fuente
4
En resumen , es la diferencia entre Shadowsy Overloadsen VB.NET.
Mark Hurd
16

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: si la clase derivada define incluso un solo 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 usingdirectiva, de modo que se conviertan en parte del "conjunto de sobrecargas" para ese nombre de método.

Daniel Earwicker
fuente
1

Según Microsoft Docs

Cuando un miembro de una clase derivada se declara con el newmodificador C # o el Shadowsmodificador Visual Basic , puede ocultar un miembro del mismo nombre en la clase base. C # oculta los miembros de la clase base mediante firma. Es decir, si el miembro de la clase base tiene múltiples sobrecargas, el único 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 tanto, IsHideBySig devuelve falseun miembro declarado con el Shadows modificador de Visual Basic y trueun miembro declarado con el newmodificador C # .

Avestura
fuente