2009-03-17 9 views
78

Utilisation d'ildasm et d'un programme C# par ex.Quel est le but de hidebysig dans une méthode MSIL?

static void Main(string[] args) 
{ 

} 

donne:

.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 

Que fait le concept de hidebysig?

Répondre

145

De ECMA 335, section 8.10.4 de partition 1:

Le CTS permet un contrôle indépendant fois sur les noms qui sont visibles à partir d'un type de base (cacher) et le partage de fentes de mise en la classe dérivée (substitution). Le masquage est contrôlé en marquant un membre de la classe dérivée comme masquer par le nom ou masquer par nom et signature. Le masquage est toujours effectué sur la base du type du membre, c'est-à-dire le champ dérivé les noms peuvent masquer les noms de champ de base, mais pas les noms de méthode, les noms de propriété ou les noms d'événements . Si un membre dérivé est marqué masquer par son nom, alors les membres de du même type dans la classe de base avec le même nom ne sont pas visibles dans la classe dérivée ; si le membre est marqué masquer par nom et signature alors seulement un membre du même type avec exactement le même nom et type (pour les champs) ou la signature de la méthode (pour les méthodes) est caché de la classe dérivée. La mise en œuvre de la distinction entre ces deux formes de masquage est fournie entièrement par le langage source compilateurs et la bibliothèque de réflexion; il n'a pas d'impact direct sur le VES lui-même.

(Il est pas évident de cela, mais hidebysig signifie "cacher par son nom et la signature".)

également dans la section 15.4.2.2 de la partition 2:

hidebysig est fourni pour l'utilisation des outils et est ignoré par le VES. Il spécifie que la méthode déclarée masque toutes les méthodes de la classe de base types qui ont une méthode correspondante signature; Lorsqu'elle est omise, la méthode doit masquer toutes les méthodes du même nom , quelle que soit la signature.

À titre d'exemple, supposons que vous avez:

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

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

... 

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

C'est valide, parce que Bar(string)ne pas cacher Bar(), parce que le compilateur C# utilise hidebysig. Si elle utilisait la sémantique "cache par nom", vous ne pourriez pas appeler Bar() sur une référence de type Derived, bien que vous puissiez toujours la convertir en Base et l'appeler comme ça.

EDIT: Je viens d'essayer ce en compilant le code ci-dessus à une DLL, il ildasming, la suppression hidebysig pour Bar() et Bar(string), ilasming encore, puis essayez d'appeler Bar() d'un autre code:

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

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

:

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

(Aucun problème de compilation.)

+2

Dans [résumé] (http://stackoverflow.com/a/4760614/256431 "Shadows vs Overloads in VB.NET"), c'est la différence entre 'Shadows' et' Overloads' dans VB.NET. –

14

Selon la réponse du SKEET, de plus, la raison en est que Java et C# permettent au client d'une classe d'appeler n'importe quelle méthode avec le même nom, y compris ceux des classes de base. Alors que C++ ne le fait pas: si la classe dérivée définit même une seule méthode avec le même nom qu'une méthode dans la classe de base, le client ne peut pas appeler directement la méthode de la classe de base, même si elle ne prend pas les mêmes arguments. La fonctionnalité a donc été incluse dans CIL pour supporter les deux approches de surcharge. En C++, vous pouvez importer un jeu de surcharges de la classe de base avec une directive using, de sorte qu'elles s'intègrent au "jeu de surcharge" pour ce nom de méthode.

Questions connexes