Je suis curieux de savoir pourquoi cela se passe. S'il vous plaît lire l'exemple de code ci-dessous et l'IL correspondant qui a été émis dans les commentaires ci-dessous chaque section:Pourquoi le compilateur C# émet-il une instruction callvirt pour un appel de méthode GetType()?
using System;
class Program
{
static void Main()
{
Object o = new Object();
o.GetType();
// L_0001: newobj instance void [mscorlib]System.Object::.ctor()
// L_0006: stloc.0
// L_0007: ldloc.0
// L_0008: callvirt instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
new Object().GetType();
// L_000e: newobj instance void [mscorlib]System.Object::.ctor()
// L_0013: call instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
}
}
Pourquoi le compilateur émet un callvirt
pour la première section, mais un call
pour la deuxième section? Y a-t-il une raison quelconque pour que le compilateur émette une instruction callvirt
pour une méthode non virtuelle? Et s'il y a des cas dans lesquels le compilateur va émettre un callvirt
pour une méthode non-virtuelle cela crée-t-il des problèmes pour la sécurité de type?
très bonne question ... m'a fait demander de l'mes livres. – Gishu
Récapitulatif: Case (1) appelle la méthode virtuelle: generate callvirt. Case (2) invoque la méthode de l'instance sur un receveur nullable: generate callvirt pour obtenir une valeur null null - oui, ceci est typeafe. Case (3) appelle une méthode d'instance sur un récepteur non annulable connu: generate appel à _avoid_ null check. Votre premier exemple tombe dans la catégorie (2), votre deuxième exemple tombe dans la catégorie (3). (Le compilateur sait que new ne renvoie jamais null et donc n'a pas besoin de vérifier à nouveau.) –
Merci Eric, la vérification de null a beaucoup de sens. Votre commentaire et la réponse de Gishu rendent les choses beaucoup plus claires! :) –