我正在开发一个包含几种不同类型数组的小项目(例如double[]
,float[]
,int[]
。为了验证/测试/健全,我正在打印我继续将这些数组中的一些放到控制台。所以我有多个函数如下所示(本例简化 - 假设我只处理单维数组):
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 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
或密封的类,但除了提及on msdn之外没有找到太多。有人可以向我解释为什么情况如此?为什么我不能指定System.Array
的类型约束?
p.s。:在输入时,我意识到我可以通过这样一个简单的功能更轻松地完成我原本想要的东西:
void Print(System.Array a)
{
for (int i = 0; i < a.Length; i++)
{
Console.Write(a.GetValue(i));
}
}
这就是编译器中数组有特殊规则的原因吗?
答案 0 :(得分:17)
执行所需操作的相应语法是:
void Print<T>(T[] array)
{
for (int i = 0; i < array.Length; i++)
{
Console.Write(array[i]);
}
}
答案 1 :(得分:0)
如果从字面上理解问题,那么Array
约束就没用了。它具有ValueType
约束是没有用的,因为它实际上并不检查您是否使用值类型作为泛型参数,但是您是否使用类型传递可分配给ValueType
所以你甚至可以传递Array
作为通用参数,它没问题。
实际有用的是拥有一个数组约束,允许任何类型派生自Array
,而不是Array
本身:
void Print<TArr>(TArr t) where TArr : array //or [*] or other fancy syntax
T
可以是[]
,[,]
,[,,]
,[,,,]
等等。唯一超过非泛型Array
参数的是我们知道数组的元素类型。
解决此问题的另一种方法是创建一个自定义Array<T>
类,其隐式运算符重载为T[]
,T[,]
,T[,,]
等。
编辑:
即使在CIL(当前)中也无法实现此目的,因为int[,]
和Array
在任何接口或构造函数中都不同。我们需要where T : Array but not Array itself
禁令。