Binding IEnumerables in C #

I would like to use IEnumerable in memory implementations with this generic extension method that I am working on. It seems to work fine with arrays, but it doesn't work with other sequences (lists and collections). here's the implementation of the method.

    // <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 this happen for some types but works for others? Could you explain the concept of this? Is there a better way to do this than my general approach? Thanks.

0


a source to share


2 answers


the documentation for GCHandle.Alloc

indicates:

It is not possible to bind an instance with non-primitive (non-blittable) members.



Object references are not primitive (also known) members. Implementation of type types List<T>

, etc. Uses object references (such as array references) internally. Thus, they have non-primitive members and cannot be pinned down.

Arrays are different: if the element type of the array is blittable (i.e. a value type with no non-flammable fields) then the array can be pinned. But that doesn't mean that the array reference can be pinned; an array reference is not an array. Collection classes such as List<T>

contain a reference to an internal storage array. They are not themselves arrays.

+7


a source


If you really need it, I suggest you call .ToArray()

and pin this.



But beware, as IEnumerable itself uses lazy evaluation / deferral, so the values ​​for the enumerable currently cannot be in memory at all. In fact, you can even have an IEnumerable that never stops.

+1


a source







All Articles