Comment les paramètres facultatifs de VB.NET fonctionnent-ils sous le capot? Sont-ils conformes à CLS?
Question
Disons que nous avons la déclaration de méthode suivante:
Public Function MyMethod(ByVal param1 As Integer, _
Optional ByVal param2 As Integer = 0, _
Optional ByVal param3 As Integer = 1) As Integer
Return param1 + param2 + param3
End Function
Comment VB.NET fait-il que les paramètres optionnels fonctionnent dans les limites du CLR? Les paramètres facultatifs sont-ils conformes à CLS?
La solution
Fait intéressant, il s'agit du code C # décompilé, obtenu via un réflecteur.
public int MyMethod(int param1,
[Optional, DefaultParameterValue(0)] int param2,
[Optional, DefaultParameterValue(1)] int param3)
{
return ((param1 + param2) + param3);
}
Notez les attributs Optional et DefaultParameterValue. Essayez de les mettre dans les méthodes C #. Vous constaterez que vous devez toujours transmettre des valeurs à la méthode. En code VB cependant, il est devenu Default! Cela étant dit, je n'ai personnellement jamais utilisé Default, même en code VB. Cela ressemble à un hack. La surcharge de méthode me convient parfaitement.
Par défaut, cela aide quand on utilise Excel Interop, ce qui est très pénible à utiliser dès la sortie de la boîte en C #.
Autres conseils
Contrairement à la croyance populaire, les paramètres facultatifs semblent être conformes à CLS. (Cependant, ma vérification principale consistait à marquer l'assembly, la classe et la méthode avec l'attribut CLSCompliant, défini sur True.)
Alors, à quoi cela ressemble-t-il dans MSIL?
.method public static int32 MyMethod(int32 param1,
[opt] int32 param2,
[opt] int32 param3) cil managed
{
.custom instance void [mscorlib]System.CLSCompliantAttribute::.ctor(bool) = ( 01 00 01 00 00 )
.param [2] = int32(0x00000000)
.param [3] = int32(0x00000001)
// Code size 11 (0xb)
.maxstack 2
.locals init ([0] int32 MyMethod)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldarg.1
IL_0003: add.ovf
IL_0004: ldarg.2
IL_0005: add.ovf
IL_0006: stloc.0
IL_0007: br.s IL_0009
IL_0009: ldloc.0
IL_000a: ret
} // end of method Module1::MyMethod
Notez les marques [opt] sur les paramètres - MSIL le supporte de manière native, sans aucun piratage. (Contrairement au support de MSIL pour le mot clé statique de VB, qui est un autre sujet.)
Alors, pourquoi ne sont-ils pas en C #? Je ne peux pas répondre à cette question, mis à part ma spéculation selon laquelle il pourrait s'agir d'un manque présumé de demande. Ma propre préférence a toujours été de spécifier les paramètres, même s'ils étaient facultatifs. Pour moi, le code est plus propre et plus facile à lire. (Si certains paramètres sont omis, je cherche souvent une surcharge correspondant à la signature visible. Ce n’est que lorsque je ne parviens pas à en trouver une que je me rends compte que des paramètres facultatifs sont impliqués.)