tags:

views:

185

answers:

2

Hi all, I'd like to pin IEnumerable implementations in memory with this generic extension method I'm working on. It seems to work fine with arrays but fails with other sequences (lists and collections). here's the method implementation.

    // <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);
    }

Why does it fail for some types but work for others?Could you explain the concept behind this? Is there a better way to do this than my generic approach? Thank you.

+7  A: 

The documentation for GCHandle.Alloc indicates:

An instance with nonprimitive (non-blittable) members cannot be pinned.

Object references are not primitive (aka blittable) members. The implementation of types like List<T> etc. use object references (such as array references) internally. Thus they have nonprimitive members and cannot be pinned.

Arrays are different: if the element type of the array is blittable (i.e. a value type with no non-blittable fields), then the array can be pinned. But that doesn't mean a reference to the array can be pinned; a reference to the array is not the array. Collection classes like List<T> contain a reference to an internal storage array. They are not arrays themselves.

Barry Kelly
Thanks for the information Barry, well explained
gogole
+1  A: 

If you really need this, I suggest you call .ToArray() and pin that.

But be careful, because IEnumerable itself uses lazy evaluation/deferred execution, and so the values for the enumerable may not currently be in memory at all. In fact, you can even have an IEnumerable that never stops.

Joel Coehoorn
Hi joel, can't believe didn't think of that. I've limited the scope of the method to arrays of T where T is a struct : public static GCHandle Pin<T>(this T[] @sequence) where T: struct. Thanks for the information.
gogole