我有一大堆需要提供给OpenGL的值类型.如果这种情况尽快发生会很棒.我现在正在做的是这样的:
List<Vertex> VList = new List<Vertex>();
... //Add vertices
Vertex[] VArray;
VList.CopyTo(VArray, VList.Length);
GL.SetData(..., VArray);
Run Code Online (Sandbox Code Playgroud)
这个列表很容易10MB,因此复制速度很慢.我可以不复制地执行此操作,就像以某种方式获取指向List内部使用的数组的指针一样?
或者我必须实现自己的List类..
编辑:我忘了提到我不知道将添加到列表中的元素数量.
Ond*_*lka 26
如果需要重复访问内部数组,最好将访问者存储为委托.
在此示例中,它是动态方法的委托.第一次调用可能不会很快,但后续调用(在相同类型的列表上)将会快得多.
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);
}
}
Run Code Online (Sandbox Code Playgroud)
确保包括:
using System.Reflection;
using System.Reflection.Emit;
Run Code Online (Sandbox Code Playgroud)
Ani*_*Ani 13
我不建议你想做什么.你为什么一开始使用a List<T>
?如果您可以准确地告诉我们您想要创建的数据结构应该具有哪些特征,以及它应该如何与消费API进行交互,我们可能能够为您的问题提供适当的解决方案.
但我会按照要求回答这个问题.
我可以不复制地执行此操作,就像以某种方式获取指向List内部使用的数组的指针一样?
是的,尽管您将依赖于未记录的实现细节.从.NET 4.0开始,调用后备阵列字段_items
.
Vertex[] vertices = (Vertex[]) typeof(List<Vertex>)
.GetField("_items", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(VList);
Run Code Online (Sandbox Code Playgroud)
请注意,这个数组几乎肯定会在最后(这是整个点)松弛List<T>
,所以array.Length
在这个数组上将不会那么有用.消耗数组的API需要通过其他方式(通过告诉它列表的真实内容Count
)通知数组的"实际"长度.
小智 8
所述的IList <T>接口并不难做到(当然,不是只要反射是免费的和功能,暗示提示).
您可以创建自己的实现并将内部数组公开为公共属性.
这不是一个好方法,但您可以使用CollectionsMarshal.AsSpan(自 .net 5 起)。它可以访问内部列表数组(参见源代码)。
var list = new List<int>();
CollectionsMarshal.AsSpan(list);
Run Code Online (Sandbox Code Playgroud)
List<T>
如果你只需要添加的能力,而不是使用反射来访问内部数组,那么我实际上建议你实现自己的可调整大小的数组(喘息!).这并不难.
就像是:
class ResizableArray<T>
{
T[] m_array;
int m_count;
public ResizableArray(int? initialCapacity = null)
{
m_array = new T[initialCapacity ?? 4]; // or whatever
}
internal T[] InternalArray { get { return m_array; } }
public int Count { get { return m_count; } }
public void Add(T element)
{
if (m_count == m_array.Length)
{
Array.Resize(ref m_array, m_array.Length * 2);
}
m_array[m_count++] = element;
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以使用内部数组InternalArray
并知道数组中有多少项Count
.