Qual è lo scopo di hidebysig in un metodo MSIL?


92

Utilizzando ildasm e un programma C # es

static void Main(string[] args)
{

}

dà:

.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

Cosa fa il costrutto hidebysig?

Risposte:


156

Da ECMA 335 , sezione 8.10.4 della partizione 1:

Il CTS fornisce un controllo indipendente sia sui nomi che sono visibili da un tipo di base (nascosto) sia sulla condivisione degli slot di layout nella classe derivata (sovrascrittura). L'occultamento è controllato contrassegnando un membro nella classe derivata come nascondi per nome o nascondi per nome e firma. L'occultamento viene sempre eseguito in base al tipo di membro, ovvero i nomi dei campi derivati ​​possono nascondere i nomi dei campi di base, ma non i nomi dei metodi, delle proprietà o degli eventi. Se un membro derivato è contrassegnato come Nascondi per nome, i membri dello stesso tipo nella classe base con lo stesso nome non sono visibili nella classe derivata; se il membro è contrassegnato come Nascondi per nome e firma, solo un membro dello stesso tipo con esattamente lo stesso nome e tipo (per i campi) o firma del metodo (per i metodi) viene nascosto dalla classe derivata. L'implementazione della distinzione tra queste due forme di occultamento è fornita interamente dai compilatori del linguaggio sorgente e dalla libreria di riflessione; non ha alcun impatto diretto sul VES stesso.

(Non è immediatamente chiaro da questo, ma hidebysigsignifica "nascondi per nome e firma".)

Anche nella sezione 15.4.2.2 della partizione 2:

hidebysig è fornito per l'uso di strumenti ed è ignorato dal VES. Specifica che il metodo dichiarato nasconde tutti i metodi dei tipi di classe base che hanno una firma del metodo corrispondente; se omesso, il metodo dovrebbe nascondere tutti i metodi con lo stesso nome, indipendentemente dalla firma.

Ad esempio, supponi di avere:

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

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

...

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

Questo è valido, perché Bar(string) non si nasconde Bar(), perché il compilatore C # usa hidebysig. Se usasse la semantica "nascondi per nome", non saresti in grado di chiamare Bar()affatto su un riferimento di tipo Derived, sebbene potresti comunque lanciarlo a Base e chiamarlo in questo modo.

EDIT: Ho appena provato questo compilando il codice di cui sopra a una DLL, ildasming esso, eliminando hidebysigper Bar()e Bar(string), ilasming di nuovo, poi cercando di chiamare Bar()da altro codice:

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

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

Però:

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

(Nessun problema di compilazione.)


4
In sintesi , è la differenza tra Shadowse Overloadsin VB.NET.
Mark Hurd

16

Secondo la risposta di THE SKEET, inoltre, la ragione di ciò è che Java e C # consentono al client di una classe di chiamare tutti i metodi con lo stesso nome, inclusi quelli delle classi base. Mentre C ++ non: se la classe derivata definisce anche un singolo metodo con lo stesso nome di un metodo nella classe base, il client non può chiamare direttamente il metodo della classe base, anche se non accetta gli stessi argomenti. Quindi la funzionalità è stata inclusa in CIL per supportare entrambi gli approcci al sovraccarico.

In C ++ è possibile importare efficacemente un insieme denominato di overload dalla classe base con una usingdirettiva, in modo che diventino parte del "set di overload" per quel nome di metodo.


1

Secondo Microsoft Docs

Quando un membro in una classe derivata viene dichiarato con il newmodificatore C # o il Shadowsmodificatore Visual Basic , può nascondere un membro con lo stesso nome nella classe base. C # nasconde i membri della classe base in base alla firma. Cioè, se il membro della classe base ha più overload, l'unico nascosto è quello che ha la firma identica. Al contrario, Visual Basic nasconde tutti gli overload della classe base. Pertanto, IsHideBySig restituisce falseun membro dichiarato con il Shadows modificatore di Visual Basic e trueun membro dichiarato con il newmodificatore C # .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.