14

我正在开发一个带有几种不同类型数组的小项目(例如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'

我一直在寻找解释(类似于或密封类,但除了在 msdn 上Object提及之外,还没有找到太多。谁能向我解释为什么会这样?为什么我不能指定类型约束?System.Array

ps:在打字的时候,我意识到我可以更容易地完成我最初想要的事情,用一个简单的函数如下:

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

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

4

2 回答 2

23

执行您想要的操作的适当语法是:

void Print<T>(T[] array)
{
    for (int i = 0; i < array.Length; i++)
    {
        Console.Write(array[i]);
    }
}
于 2013-02-10T05:31:33.770 回答
-1

如果从字面上理解这个问题,那么有一个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约束。

于 2015-01-01T15:17:12.427 回答