【发布时间】:2018-06-14 13:22:09
【问题描述】:
去年我问过如何遍历和打印锯齿状数组,而不必为每个添加的维度编写重载函数。 Generic printing of jagged arrays.
我再次发现了这个问题,并且能够像这样解决它。这与我得到的答案之一相似,但并不完全相同。
static string Print<T>(T[] array)
{
string str = "[ ";
for (int i = 0; i < array.Length; i++)
{
str += array[i];
if (i < array.Length - 1)
str += ", ";
}
return str + " ]\n";
}
static string Print<T>(T[][] array)
{
string str = "";
for (int i = 0; i < array.Length; i++)
{
var sub = array[i];
if (sub.Length != 0 && sub[0] is Array)
str += PrintDynamic(sub);
else
str += Print(sub);
}
return str + "\n";
}
private static string PrintDynamic(dynamic array)
{
return Print(array);
}
它工作正常,我得到正确的输出:
var twoDim = new int[][]
{
new int[] { 0, 1, 2, 3 },
new int[] { 0, 1, 2 },
new int[] { 0 }
};
var threeDim = new int[][][] { twoDim, twoDim }
Console.WriteLine(Print(threeDim));
// Output:
// [ 0, 1, 2, 3]
// [ 0, 1, 2]
// [ 0 ]
//
// [ 0, 1, 2, 3]
// [ 0, 1, 2]
// [ 0 ]
但我仍然不满意,因为如果我不需要PrintDynamic(),如果我可以写会更好
str += Print(sub);
而不是
str += PrintDynamic(sub);
这就是我的问题的来源。如果我更改那一行,我不会收到任何错误,但输出变为
// [ System.Int32[], System.Int32[], System.Int32[], System.Int32[]]
// [ System.Int32[], System.Int32[], System.Int32[]]
// [ System.Int32[] ]
//
// [ System.Int32[], System.Int32[], System.Int32[], System.Int32[]]
// [ System.Int32[], System.Int32[], System.Int32[]]
// [ System.Int32[] ]
因为Print<T>(T[] array) 被调用而不是Print<T>(T[][] array)。当从PrintDynamic(dynamic array) 调用时,编译器如何知道要使用哪个Print<T>(),但从Print<T>() 内调用时却不知道?
【问题讨论】:
-
重载分辨率是一个复杂的课题!
-
简而言之-编译器不知道
dynamic的情况。 DLR 在运行时使用反射解决它。 -
因此即使
Print<T>(T[][] array)接受超过2维的锯齿状数组作为参数,它仍然会认为array[i]始终是一维数组,因此编译器将始终调用Print<T>(T[] array)?那么在运行时调用的 2 个方法中的哪一个并没有真正解决? -
@AlexanderMoser:是的,我已经解释了第二个答案,它正确地描述了为什么你的代码会这样。
标签: c# generics dynamic overload-resolution