为什么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
约束。