当我运行此程序时,我在包含 fn(3,4)
的行上出现两个错误参数1:无法从'int'转换为T
参数2:无法从'int'转换为T
我认为类型T将是int,由lambda指定。但如果是这样,为什么转换错误呢?我误解了什么吗?
class Program
{
static void DoStuff<T>(Func<T, T, T> fn)
{
Console.WriteLine(fn(3, 4));
}
static void Main()
{
DoStuff((int x, int y) => x + y);
}
}
如果我更改参数以接受int作为参数:
,这是有效的class Program
{
static void DoStuff<T>(T x, T y, Func<T, T, T> fn)
{
Console.WriteLine(fn(x, y));
}
static void Main()
{
DoStuff(3, 4, (int x, int y) => x + y);
}
}
我来自C ++背景,因此试图了解C#中哪些有效,哪些无效#
答案 0 :(得分:8)
在DoStuff<T>
方法中,T
的实际类型未知;您的代码会将int
传递给函数,假设T
为int
,但T
实际上可以是任何内容,例如string
,所以您将通过int
到仅接受string
s。
RE“我来自C ++背景,因此试图了解C#中的有效和无效的内容”:
C#泛型看起来与C ++模板类似,但它们实际上完全不同。
在C ++中,模板在编译时根据用法进行实例化;如果对T使用3种不同类型的模板方法,编译器将生成3种不同的方法。模板方法的主体不必对任何T
有效,只要它对实际使用情况有效。 (对不起,如果我的解释不完全准确;我不太了解C ++)
在C#中,没有基于用法的编译时生成;编译器只生成1个泛型方法,并且运行时生成给定T
的实际运行时方法。为了确保这一点,C#编译器必须确保方法体对任何T
都有效(或者如果您为T
指定了约束,那么任何T
都符合约束条件。这就是为什么你的第一个片段出现错误的原因:只有当T
为int
时,泛型方法的正文才有效。
我建议你阅读this question的答案,以获得更详细的解释。
答案 1 :(得分:1)
这里不需要使用泛型。变化
static void DoStuff<T>(Func<T, T, T> fn)
到
static void DoStuff(Func<int, int, int> fn)