2009-05-21 4 views
0

Je voudrais épingler les implémentations IEnumerable en mémoire avec cette méthode d'extension générique sur laquelle je travaille. Il semble fonctionner correctement avec les tableaux mais échoue avec d'autres séquences (listes et collections). voici la mise en œuvre de la méthode.Pinning IEnumerables in C#

// <summary> 
    /// Pins an IEnumerable of type T in memory 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <param name="sequence"></param> 
    /// <returns></returns> 
    public static GCHandle Pin<T>(this IEnumerable<T> @sequence) 
    { 
     return GCHandle.Alloc(@sequence, GCHandleType.Pinned); 
    } 

Pourquoi est-ce que cela échoue pour certains types mais fonctionne pour d'autres? Pouvez-vous expliquer le concept derrière cela? Y a-t-il une meilleure façon de faire cela que mon approche générique? Je vous remercie.

Répondre

7

Le documentation pour GCHandle.Alloc indique:

Un exemple avec les membres non primitif (non blittable) ne peuvent être épinglés.

Les références d'objet ne sont pas des membres primitifs (aka blittable). L'implémentation de types tels que List<T> etc. utilise des références d'objet (telles que des références de tableau) en interne. Ainsi, ils ont des membres non primitifs et ne peuvent pas être épinglés.

Les tableaux sont différents: si le type d'élément de la matrice est blittable (c'est-à-dire un type de valeur sans champs non blittables), alors le tableau peut être épinglé. Mais cela ne signifie pas qu'une référence au tableau peut être épinglée; une référence au tableau n'est pas le tableau. Les classes de collection telles que List<T> contiennent une référence à une matrice de stockage interne. Ils ne sont pas des tableaux eux-mêmes.

+0

Merci pour l'information Barry, bien expliqué – gogole

1

Si vous vraiment besoin de cela, je vous suggère d'appeler .ToArray() et épingler cela.

Mais attention, étant donné que IEnumerable lui-même utilise une évaluation paresseuse/une exécution différée, les valeurs de l'énumérable ne peuvent actuellement pas être en mémoire du tout. En fait, vous pouvez même avoir un IEnumerable qui ne s'arrête jamais.

+0

Salut joel, ne peut pas croire ne pas penser à ça. J'ai limité la portée de la méthode aux tableaux de T où T est une structure: publique GCHandle Pin statique (cette T [] @sequence) où T: struct. Merci pour l'information. – gogole