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.
The documentation for
GCHandle.Allocindicates: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.