web-dev-qa-db-fra.com

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

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?

88
nzpcmad

De ECMA 335 , section 8.10.4 de la partition 1:

Le CTS fournit un contrôle indépendant sur les noms qui sont visibles à partir d'un type de base (masquage) et le partage des emplacements de disposition dans la classe dérivée (redéfinition). Le masquage est contrôlé en marquant un membre de la classe dérivée comme masqué par 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 champ dérivés 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énement. Si un membre dérivé est marqué masquer par son nom, les membres 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, 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 de 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, mais hidebysig signifie "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.

Par 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 masque pas Bar(), car le compilateur C # utilise hidebysig. S'il utilisait la sémantique "masquer par nom", vous ne pourriez pas appeler du tout Bar() sur une référence de type Derived, bien que vous puissiez toujours le caster 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'illustrant, en supprimant hidebysig pour Bar() et Bar(string), en l'illustrant à nouveau, puis en essayant pour 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.)

152
Jon Skeet

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 du même nom, y compris celles des classes de base. Tandis que C++ le fait non: si la classe dérivée définit même une seule méthode portant 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 soutenir les deux approches de la surcharge.

En C++, vous pouvez effectivement importer un ensemble nommé de surcharges de la classe de base avec une directive using, afin qu'elles deviennent une partie de l '"ensemble de surcharge" pour ce nom de méthode.

15
Daniel Earwicker

Selon Microsoft Docs

Lorsqu'un membre d'une classe dérivée est déclaré avec le modificateur C # new ou le modificateur Visual Basic Shadows, 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 signature identique. En revanche, Visual Basic masque toutes les surcharges de classe de base. Ainsi, IsHideBySig renvoie false sur un membre déclaré avec le modificateur Visual Basic Shadows et true sur un membre déclaré avec C # new modificateur.

1
0xaryan