2009-03-14 7 views
12

J'ai simple code C#:boxe lors de l'utilisation des médicaments génériques en C#

private Stack<Person> m_stack = new Stack<Person>(); 

public void Add<T>(T obj) 
    where T : Person 
{ 
    m_stack.Push(obj); 
} 

Cela produira le code IL suivant:

.method public hidebysig instance void 
      Add<(ConsoleApplication1.Person) T>(!!T obj) cil managed 
    { 
    // Code size  20 (0x14) 
    .maxstack 8 
    IL_0000: nop 
    IL_0001: ldarg.0 
    IL_0002: ldfld  class [System]System.Collections.Generic.Stack`1<class ConsoleApplication1.Person> ConsoleApplication1.Pool::m_stack 
    IL_0007: ldarg.1 
    IL_0008: box  !!T 
    IL_000d: callvirt instance void class [System]System.Collections.Generic.Stack`1<class ConsoleApplication1.Person>::Push(!0) 
    IL_0012: nop 
    IL_0013: ret 
    } // end of method Pool::Add 

Donc, ma question est ... pourquoi la boxe? (IL_0008) Je peux comprendre le downcasting ou même compiler l'erreur, mais pourquoi la boxe (Personne est un type de référence ...)

Merci d'avance!

Répondre

4

Je crois qu'il est la contrainte de méthode générique qui fait cela pour vous - mais ...

Dans tous les cas, il n'y a pas besoin de la méthode générique du tout. Il suffit de l'écrire comme:

 
public void Add(Person person) 
{ 
    m_stack.Push(person); 
} 

Vous verrez que l'IL se simplifie et évite complètement la question. Si vous êtes contraint à un type de référence spécifique, vous pouvez simplement utiliser ce type de référence.

Ceci est beaucoup plus facile à comprendre et beaucoup plus clair. Je suggère d'éviter l'appel de méthode générique sauf si c'est vraiment nécessaire. Les méthodes génériques rendent la classe moins évidente, ce qui signifie moins lisibles et maintenables à long terme, et plus difficile à utiliser.

+0

@ Reed: Oui, voici comment j'ai résolu le problème, mais j'étais curieux de savoir pourquoi le type de référence est encadré (n'a aucun sens) ... –

+0

Je pense que c'est une implémentation du fonctionnement des méthodes génériques. Notez que c'est la boxe T, pas la personne. Vous n'êtes jamais en train de boxer/déballer votre classe, mais c'est quelque chose de "extra" qui finit dans les appels de méthodes génériques. Je ne sais pas pourquoi, cependant. –

30

Extrait de ECMA-335 Partition III 4,1

Si typeTok est un type de référence, l'instruction de la boîte ne fait rien.

typeTok est !! T dans votre cas. Je suppose que lorsque le compilateur compile le code, il appelle toujours la case , que le type de l'opérande soit de type référence ou non. En raison de la sémantique de l'instruction box, le résultat souhaité est toujours garanti.

+0

c'est la bonne réponse. – JaredPar

+0

+1 Beau travail de suivi vers le bas. Bonne information. Est-ce que cette instruction serait également supprimée par le JIT, ou est-ce que cela provoquerait la fermeture d'une instruction noop? –

Questions connexes