Quel est le but de hidebysig dans une méthode MSIL?


92

Utiliser ildasm et un programme C #, par exemple

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 la construction hidebysig?

Réponses:


156

D'après ECMA 335 , section 8.10.4 de la partition 1:

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

(Ce n'est pas immédiatement clair à partir de cela, mais hidebysigsignifie "masquer par nom et signature".)

Également dans la section 15.4.2.2 de la partition 2:

hidebysig est fourni pour l'utilisation d'outils et est ignoré par le VES. Il spécifie que la méthode déclarée masque toutes les méthodes des types de classe de base qui ont une signature de méthode correspondante; 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 ayez:

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

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

...

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

C'est valide, car Bar(string) ne se cache pasBar() , car le compilateur C # utilise hidebysig. S'il utilisait la sémantique "hide by name", vous ne pourriez pas du tout appeler Bar()une référence de type Derived, bien que vous puissiez toujours la convertir en Base et l'appeler de cette façon.

EDIT: Je viens d'essayer cela en compilant le code ci-dessus dans une DLL, en l'ildasming, en le supprimant hidebysigpour Bar()et Bar(string), en le réenregistrant, puis en essayant d'appeler à Bar()partir d'un autre code:

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

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

Toutefois:

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

(Aucun problème de compilation.)


4
En résumé , c'est la différence entre Shadowset Overloadsdans VB.NET.
Mark Hurd

16

Selon la réponse de THE SKEET, en outre, la raison en est que Java et C # permettent au client d'une classe d'appeler toutes les méthodes portant le même nom, y compris celles des classes de base. Alors que C ++ ne le fait pas: si la classe dérivée définit ne serait-ce qu'une seule méthode avec le même nom qu'une méthode de la classe de base, alors 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 prendre en charge les deux approches de la surcharge.

En C ++, vous pouvez effectivement importer un ensemble nommé de surcharges à partir de la classe de base avec une usingdirective, afin qu'elles deviennent partie intégrante du «jeu de surcharges» pour ce nom de méthode.


1

Selon Microsoft Docs

Lorsqu'un membre d'une classe dérivée est déclaré avec le newmodificateur C # ou le Shadowsmodificateur Visual Basic , il peut masquer un membre du même nom dans la classe de base. C # masque les membres de la classe de base par signature. Autrement dit, si le membre de la classe de base a plusieurs surcharges, le seul qui est masqué est celui qui a la même signature. En revanche, Visual Basic masque toutes les surcharges de classe de base. Ainsi, IsHideBySig retourne falsesur un membre déclaré avec le Shadows modificateur Visual Basic et truesur un membre déclaré avec le newmodificateur C # .

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.