调用泛型方法

时间:2016-09-30 11:18:09

标签: c# generics

假设我有一个通用方法。调用方法与指定类型和调用没有它有什么区别。

什么时候必须指定类型?

Write(1);
Write<int>(1);
Write<string>("test"); 
Write("test");

private static void Write<T>(T param)
{
    Console.WriteLine(param);
}

4 个答案:

答案 0 :(得分:5)

编译器将尝试在编译时解析type参数。在可能的情况下,它是自动完成的,您无需指定显式类型。在所有其他情况下,当编译器无法确定类型参数时,编译器将抛出错误,您无法编译应用程序。

在您的示例Write(1)中,参数1的类型为int。因此编译器推断T必须是int,因此调用等同于Write<int>(1)。与Write("test")类似,"test"的类型为string,因此编译器会推断Tstring

这通常适用于传递给函数的参数的编译时类型。因此,如果您的编译时类型为object的字符串,则T将为object

object arg = "foo";

Write(arg); // arg is object

// this is equivalent to this:
Write<object>(arg);

因此,虽然您传递的是字符串,但其编译时类型为object,因此这是唯一的信息,编译器可以在这里使用。

此外,如果希望编译器使用与传递给它的编译时参数不同的类型,则可能需要显式指定类型参数。在上面的示例中,您可以使用Write<object>(1),这会导致整数1转换为object。但是,实际上这通常会破坏泛型方法的目的,即使您不需要访问实际参数的编译时类型,也可能会产生实际后果。例如,值类型在作为object传递时会被装箱,但泛型方法允许您将它们保存为值类型 - 请记住,泛型方法定义(同样适用于类型)等同于使用<指定重载em>每个其他有效的泛型类型参数值(因此您通常拥有无限的方法副本)。

当然,编译器的类型推断也适用于多个参数:

void Write<T1, T2>(T1 arg1, T2 arg2)
{ … }

Write(1, "foo");
// is equivalent to
Write<int, string>(1, "foo");

但是,当编译器甚至无法推断出一个类型参数时,您必须在调用中指定它们的所有

答案 1 :(得分:3)

在这种情况下,它不是强制性的,因为参数param是通用的(编译器会像那样解析它)。

这意味着只要type参数不作为参数提供,它就是强制性的。

答案 2 :(得分:2)

当编译器无法推断时,或者当您对编译器推断的内容不满意时,必须指定类型。

答案 3 :(得分:1)

之间没有区别
Write<string>("test");
Write("test");

但是,当你指定的不是参数的确切类型,而是可转换时,例如

Write<object>("test");
Write("test");

尝试打印类型参数,会看到差异

private static void Write<T>(T param)
{
    Console.WriteLine(typeof(T));
    Console.WriteLine(param);
}