系统阵列背后的奥秘



我们知道System.Array是一个抽象类,无论我们使用什么DataType[]运行时都会以某种方式为我们创建一些具体的实现(虽然模糊)。

请考虑以下代码片段。

int[] someInts = { 1, 2, 3, 4 };
IList<int> collection = someInts;
collection.Clear();

collection.Clear()NotSupportedException,没什么好惊讶的。当我检查看到"StackTrace"时,惊讶地发现它在调用堆栈的顶部显示了一些奇怪的"类型"SZArrayHelper

堆栈跟踪:

   at System.SZArrayHelper.Clear[T]()//Note this.. How???
   at TestApplication.Program.Main()

这怎么可能呢? 我在int[]上调用Clear()方法,但是调用如何转到SZArrayHelper.Clear. 请注意,Clear 是实例方法,SZArrayHelper定义如下。

private void Clear<T>()
{
    throw new NotSupportedException(Environment.GetResourceString("NotSupported_ReadOnlyCollection"));
}

谁创建了"SZArrayHelper"的实例,并注意清除方法是私有的。我对正在发生的事情感到非常困惑。如果创建了"SZArrayHelper"的实例并调用了Clear则执行此调用的帮助程序方法应该位于"StackTrace"中。但这里的情况并非如此。

有人可以解释一下幕后发生的事情吗?

注意:

  1. int[]只是一个例子,你几乎可以用任何类型的数组来模拟它,不仅Clear方法AddContains等都具有相同的行为。

  2. 尝试使用反射器插件进行调试,这给了我相同的结果。调试器显示对 SZArrayHelper.Clear<T>() 的直接调用。

  3. Google将我带到了这个.NET Arrays,IList,Generic Algorithms,以及STL呢?这有助于理解幕后发生的那种魔力,但仍然存在一些谜团。

您没有看到对该方法的任何调用,因为您自己调用它,尽管这听起来很奇怪。 SZArrayHelper 是围绕数组的 CLR 包装器,它实现IList<T>接口,有点像适配器模式。

从这个角度来看,collection.Clear直接调用SZArrayHelper.Clear是有道理的。

Hans Passant在这里很好地解释了这一点:https://stackoverflow.com/a/11164210/857807

最新更新