Overriding et Shadowing de méthodes en IL.

Publié par Fabrice Michellonet sous le(s) label(s) le 23 avril 2010

En ce moment je fais joujou avec les opcodes CIL qui se cachent sous notre bon vieux C#.

En voulant surcharger et cacher (shadow) successivement deux propriétés hérités, j'ai remarqué que le compilo générait une suite de metadata assez déroutante. Prenons l'exemple suivant :

public class BaseClass
    {
        public int Prop1 { get; set; }
        public virtual int Prop2 { get; set; }
        public virtual int Prop3 { get; set; }
    }

    public class DerivClass : BaseClass
    {
        public int Prop1 { get; set; }
        public new int Prop2 { get; set; }
        public new virtual int Prop3 { get; set; }
    }

Du coté de la classe de base on obtient les metadata suivantes sur le getter :

non virtual :

.method public hidebysig specialname instance int32 get_Prop1() cil managed
virtual :
.method public hidebysig specialname newslot virtual instance int32 get_Prop2() cil managed
remarquez l'utilisation conjointes des metadata virtual et newslot, je reviendrais dessus juste après.

Côté classe dérivée on obtient cela :

non virtual :

.method public hidebysig specialname instance int32 get_Prop1() cil managed
new :
.method public hidebysig specialname instance int32 get_Prop2() cil managed
virtual new :
.method public hidebysig specialname newslot virtual instance int32 get_Prop3() cil managed

Oulaaa... c'est la que ca se corse!! Dans la classe de base, comme je vous le faisait remarquer précédemment, le compilo utilise conjointement les metadata virtual et newslot. Logiquement, on aurait pu s'attendre a voir uniquement le virtual.

Dans la classe dérivée, le shadowing non virtuel

public new int Prop2 { get; set; }
produit des metadata token strictement identiques à une propriété normale; et le shadowing virtuel produit un IL identique à propriété virtuelle.

De ces constatation on peut en déduire que : Le token newslot, ne suffit pas à affirmer qu'il s'agit d'une shadowing methode (le getter non-virtuel de la classe de base et le getter new de la classe dérivée ayant les mêmes metadata).

Par contre, si une méthode contient le token virtual mais pas le newslot, alors c'est qu'il s'agit a coup sur d'un overriding et pas un shadowing.

Par déduction, on peut donc penser que si une méthode n'est pas un overriding (le token newslot est présent), alors il n'y a shadowing que si la signature [type de retour, nom et paramètres de la méthode] de la méthode existe également dans la classe de base.