泛型方法的重载解析未按预期工作

亚历山大·摩瑟

去年,我问过如何遍历和打印锯齿状数组,而不必为要添加的每个维编写重载函数。锯齿状阵列的通用打印
我再次遇到了问题,并能够像这样解决它。它与我得到的答案之一相似,但不完全相同。

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)Print<T>()从调用时编译器如何知道使用哪个PrintDynamic(dynamic array),而从内部调用时却不知道Print<T>()

鲍德里克

回答您的原始问题。你打电话时:

str += Print(sub)

并且该方法的原始对象是int[][][],则<T>该方法的是int[]所以,你在呼唤Print(sub)T[],哪里Tint[]

因此,选择asT[]重载Print,并且-一切都按预期进行。这是在编译时解决的,并且是编译器可以最好地利用其所拥有的信息。Tint[]

请记住,一个通用方法只能编译到IL一次-您不会因为碰巧调用它的方式不同而获得“不同版本”(与C ++模板不同)。通用方法的行为必须对所有可能的输入均有效。因此,如果该方法接收T[][],并且您在内部提取了子元素,则它只能将子对象类型视为T[]它在运行时无法检测到“哦,实际上T是一个int [],所以我将调用另一个重载”。无论输入什么,该方法都只会调用T[]重载Print(sub)

但是,在使用的情况下dynamic,您将忽略在编译时产生的所有通用类型信息,而是说“在运行时使用反射现在实际上是什么类型”。现在哪种方法最合适?使用那个!此行为的开销很大,因此必须通过使用dynamic关键字来显式请求

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章