Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
148 views
in Technique[技术] by (71.8m points)

c# - List<T> to T[] without copying

I'm have a large list of value types that needs to be given to OpenGL. It would be great if this could happen as quickly as possible. What I'm doing now looks like this:

List<Vertex> VList = new List<Vertex>();
... //Add vertices
Vertex[] VArray;
VList.CopyTo(VArray, VList.Length);
GL.SetData(..., VArray);

This list is easily 10MB big, so copying is slow. Can I do this without copying, like somehow get a pointer to the array used internally by List?

Or do I have to implement my own List class..

EDIT: I forgot to mention that I don't know the number of elements that will be added to the List.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

If you need to access internal array repeatedly, it good practice to store accessor as delegate.

In this example, it's delegate to dynamic method. First call may not be fast, but subsequent calls (on List of same type) will be much faster.

public static class ListExtensions
{
    static class ArrayAccessor<T>
    {
        public static Func<List<T>, T[]> Getter;

        static ArrayAccessor()
        {
            var dm = new DynamicMethod("get", MethodAttributes.Static | MethodAttributes.Public, CallingConventions.Standard, typeof(T[]), new Type[] { typeof(List<T>) }, typeof(ArrayAccessor<T>), true);
            var il = dm.GetILGenerator();
            il.Emit(OpCodes.Ldarg_0); // Load List<T> argument
            il.Emit(OpCodes.Ldfld, typeof(List<T>).GetField("_items", BindingFlags.NonPublic | BindingFlags.Instance)); // Replace argument by field
            il.Emit(OpCodes.Ret); // Return field
            Getter = (Func<List<T>, T[]>)dm.CreateDelegate(typeof(Func<List<T>, T[]>));
        }
    }

    public static T[] GetInternalArray<T>(this List<T> list)
    {
        return ArrayAccessor<T>.Getter(list);
    }
}

Make sure to include:

using System.Reflection;
using System.Reflection.Emit;

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...