2009-03-17 7 views
78

Verwenden von Ildasm und einem C# -Programm, z.B.Was ist der Zweck von hidebysig in einer MSIL-Methode?

static void Main(string[] args) 
{ 

} 

gibt:

.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 

Was bedeutet das hidebysig Konstrukt tun?

Antwort

145

Von ECMA 335, Abschnitt 8.10.4 der Partition 1:

Die CTS bietet unabhängige Steuerung sowohl über die Namen, die von einer Basis Typ (Versteck) und die gemeinsame Nutzung von Layout Schlitze sichtbar sind in die abgeleitete Klasse (überschreiben). Versteckt ist gesteuert durch Markierung eines Mitglieds in der abgeleiteten Klasse als entweder durch den Namen verbergen oder durch Name-und-Signatur ausblenden. Das Ausblenden von wird immer basierend auf der Art des Elements durchgeführt, dh abgeleitete Feld Namen können Base-Feldnamen, aber nicht Methodennamen, Eigenschaftsnamen oder Ereignisnamen ausblenden. Wenn ein abgeleiteter Member mit Namen ausschließen markiert ist, dann sind Mitglieder von derselben Art in der Basisklasse mit denselben Namen nicht in der abgeleiteten Klasse sichtbar; Wenn das Mitglied als mit Namen und Signatur gekennzeichnet ist, dann ist nur ein Mitglied desselben Typs mit exakt desselben Namens und Typs (für Felder) oder Methodensignatur (für Methoden) aus der abgeleiteten Klasse ausgeblendet. Implementierung der Unterscheidung zwischen diesen beiden Formen des Versteckens ist zur Verfügung gestellt von Quellsprache Compiler und die Reflexionsbibliothek; es hat keinen direkten Einfluss auf die VES selbst.

(Es ist nicht sofort klar, dass, aber hidebysig Mittel "verstecken von Namens- und Unterschrift".)

Auch in Abschnitt 15.4.2.2 der Trennwand 2:

hidebysig ist geliefert für die Verwendung von Tools und wird von der VES ignoriert. Es gibt an, dass die deklarierte Methode alle Methoden der Basisklasse Typen ausblendet, die eine übereinstimmende Methode Signatur haben; Wenn sie weggelassen wird, sollte die Methode alle Methoden desselben Namens verbergen, unabhängig von der Signatur.

Als Beispiel: Angenommen, Sie haben:

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

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

... 

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

, die gültig ist, weil Bar(string)nicht verstecken Bar(), weil der C# -Compiler hidebysig verwendet. Wenn Sie die Semantik "Verbergen nach Namen" verwenden würden, könnten Sie Bar() überhaupt nicht auf einer Referenz vom Typ Derived aufrufen, obwohl Sie es immer noch in Base umwandeln und es so nennen könnten.

EDIT: Ich habe gerade versucht, dies durch den obigen Code auf eine DLL kompilieren, ildasming es, das Entfernen hidebysig für Bar() und Bar(string), es ilasming wieder, dann versucht Bar() von anderen Code aufzurufen:

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

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

jedoch:

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

(Keine Kompilierungsproblemen.)

+2

In [Zusammenfassung] (http://stackoverflow.com/a/4760614/256431 "Shadows vs Überladungen in VB.NET"), ist es der Unterschied zwischen 'Shadows' und' Overloads' in VB.NET. –

14

gemäß der Antwort der SKEET, Der Grund hierfür ist, dass Java und C# dem Client einer Klasse erlauben, alle Methoden mit demselben Namen aufzurufen, einschließlich solcher aus Basisklassen. C++ dagegen nicht: Wenn die abgeleitete Klasse selbst eine einzige Methode mit demselben Namen wie eine Methode in der Basisklasse definiert, kann der Client die Basisklassenmethode nicht direkt aufrufen, auch wenn er nicht dieselben Argumente annimmt. Daher wurde das Feature in CIL integriert, um beide Überlastungsansätze zu unterstützen.

In C++ können Sie effektiv einen benannten Satz von Überladungen aus der Basisklasse mit einer using Direktive importieren, so dass sie Teil des "overload set" für diesen Methodennamen werden.