在 dotnet 中,array 是区分类型的,生成一个 T[] 数组,就不能在其中存入不是 T(及其子类)的元素。对于引用类型,CLR 会对存入的元素做类型检查。不过由于值类型是不能继承的,所以值类型的数组就不存在这样的检查。可以利用这一点来避免对引用类型数组进行类型检查的开销,从而提高存入性能。虽然数组性能已经很不错了,但有时候性能的这一点提高也有帮助。
我们可以创建一个对引用类型的值类型包装,如下:
public struct ObjectWrapper
{
public readonly object Instance;
public ObjectWrapper(object instance)
{
Instance = instance;
}
}
然后使用这个值类型来创建数组,这样在设置数组值 ObjectWrapperArray[i] = objectWrapperInstance 时就不会有类型检查了。性能会有一定的提升。
Roslyn 代码库里面的 ObjectPool<T> 也利用了这样的技巧:
internal class ObjectPool<T> where T : class
{
[DebuggerDisplay("{Value,nq}")]
private struct Element
{
internal T Value;
}
// Storage for the pool objects. The first item is stored in a dedicated field because we
// expect to be able to satisfy most requests from it.
private T _firstItem;
private readonly Element[] _items;
// other members ommitted for brievity
}