为什么System.Array不能成为类型约束?

我正在开发一个带有几种不同类型数组的小项目(例如double[]float[]int[] 。为了validation/测试/健全,我将其中一些数组打印到控制台我继续。所以我有多个函数,如下所示(本例简化 – 假设我只处理单维数组):

 void Print(float[] a) // prints an array of floats { for (int i = 0; i < a.Length; i++) { Console.Write(a[i]); } } void Print(double[] a) // prints an array of doubles { for (int i = 0; i < a.Length; i++) { Console.Write(a[i]); } } 

我以我的无限智慧认为,我可以通过简单地创建这些函数的通用版本来减少一些代码重复。 所以我尝试了这个:

 void Print(T t) where T : Array { for (int i = 0; i < t.Length; i++) { Console.Write(t.GetValue(i)); } } 

Intellisense没有抱怨,但编译器失败并出现一个非常有趣的错误:

Constraint cannot be special class 'System.Array'

我已经找了一个解释(类似于Object或密封类,但除了在msdn上提到之外没有找到太多。有人可以向我解释为什么会这样吗?为什么我不能指定System.Array的类型约束System.Array

ps:在输入时,我意识到我可以更容易地完成我原本想要的东西,使用这样一个简单的函数:

 void Print(System.Array a) { for (int i = 0; i < a.Length; i++) { Console.Write(a.GetValue(i)); } } 

这就是为什么编译器中有一个特殊的数组规则?

执行所需操作的相应语法是:

 void Print(T[] array) { for (int i = 0; i < array.Length; i++) { Console.Write(array[i]); } } 

如果从字面上理解问题,那么拥有一个Array约束就没用了。 它具有ValueType约束是没有用的,因为它实际上不检查您是否使用值类型作为generics参数,但是您传递的类型是否可赋值给ValueType
所以你可以传递偶数Array作为generics参数,它没关系。

实际上有用的是使用数组禁令允许从Array派生的任何类型,而不是Array本身:

 void Print(TArr t) where TArr : array //or [*] or other fancy syntax 

其中T可以是[][,][,,][,,,]等。 唯一的非genericsArray参数是我们知道数组的元素类型。

解决此问题的另一种方法是使用T[]T[,]T[,,]等隐式运算符重载创建自定义Array类。

编辑:
即使在CIL(当前)中也无法实现这一点,因为int[,]Array在任何接口或构造函数中都没有区别。 我们需要where T : Array but not Array itself约束。