2009-03-17 13 views
78

Utilizzando ildasm e un programma C# ad es.Qual è lo scopo di hidebysig in un metodo MSIL?

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

risposta

145

Da ECMA 335, sezione 8.10.4 di partizione 1:

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

(Non è immediatamente chiaro a questo, ma hidebysig significa "nascondere per nome-e-firma".)

anche nella sezione 15.4.2.2 della partizione 2:

hidebysig è fornito per l'uso degli strumenti e viene ignorato dal VES. E ' specifica che il metodo dichiarato nasconde tutti i metodi della classe base tipi che hanno un metodo di corrispondenza firma; se omesso, il metodo dovrebbe nascondere tutti i metodi dello stesso nome , indipendentemente dalla firma.

A titolo di esempio, si supponga 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 lo fa nascondere Bar(), perché il compilatore C# utilizza hidebysig. Se si fosse utilizzata la semantica "nascondi per nome", non si sarebbe in grado di chiamare Bar() su un riferimento di tipo Derived, sebbene si possa ancora trasmettere su Base e chiamarlo in questo modo.

EDIT: Ho appena provato questo compilando il codice di cui sopra a una DLL, ildasming esso, eliminando hidebysig per 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 

Tuttavia:

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

(Nessun problema di compilazione.)

+2

In [summary] (http://stackoverflow.com/a/4760614/256431 "Ombre contro sovraccarichi in VB.NET"), è la differenza tra "Ombre" e "Sovraccarichi" in VB.NET. –

14

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

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