通常,在C#中使用List比使用T []更方便。但是,有时候分析器显示List与Array.Copy和Buffer.BlockCopy等本机实现的批量操作相比具有显着的性能损失。此外,无法获得指向List<>的指针。元件。
这使得使用Unity中的动态网格有点痛苦。如果我们可以访问 T [] List._items ,可以减轻其中一些问题。这可能没有显着的开销吗? (无论是CPU还是垃圾)
答案 0 :(得分:0)
始终可以使用反射。这会为 GetValue()的调用生成几百个字节的垃圾。它也不是很快;大约40列表< T>访问。
// Helper class for fetching and caching FieldInfo values
class FieldLookup {
string sm_name;
Dictionary<Type, FieldInfo> sm_cache;
public FieldLookup(string name) {
sm_name = name;
sm_cache = new Dictionary<Type, FieldInfo>();
}
public FieldInfo Get(Type t) {
try {
return sm_cache[t];
} catch (KeyNotFoundException) {
var field = sm_cache[t] = t.GetField(
sm_name,
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.GetField |
System.Reflection.BindingFlags.Instance);
return field;
}
}
}
static FieldLookup sm_items = new FieldLookup("_items");
public static T[] GetBackingArray<T>(this List<T> list) {
return (T[])sm_items.Get(typeof(List<T>)).GetValue(list);
}
答案 1 :(得分:0)
如果您知道List的布局,那么您可以使用脏技巧来转换托管对象引用。除非您愿意在所运行的每个目标平台上进行测试,否则不要使用它,并在每次Unity升级时重新测试。
最危险的是它打破了关于运行时和对象的编译类型的不变量。编译器将为TTo类型的对象生成代码,但对象的RTTI字段仍将显示TFrom类型的对象。
[StructLayout(LayoutKind.Explicit)]
public struct ConvertHelper<TFrom, TTo>
where TFrom : class
where TTo : class {
[FieldOffset( 0)] public long before;
[FieldOffset( 8)] public TFrom input;
[FieldOffset(16)] public TTo output;
static public TTo Convert(TFrom thing) {
var helper = new ConvertHelper<TFrom, TTo> { input = thing };
unsafe {
long* dangerous = &helper.before;
dangerous[2] = dangerous[1]; // ie, output = input
}
var ret = helper.output;
helper.input = null;
helper.output = null;
return ret;
}
}
class PublicList<T> {
public T[] _items;
}
public static T[] GetBackingArray<T>(this List<T> list) {
return ConvertHelper<List<T>, PublicList<T>>.Convert(list)._items;
}