Reputation: 1826
When I run this program I get two errors on the line containing fn(3,4)
Argument 1: cannot convert from 'int' to T
Argument 2: cannot convert from 'int' to T
I thought type T would be int, as specified by the lambda. But if so then why the conversion errors? Am I misunderstanding something?
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);
}
}
This works, if I change the parameters to accept the ints as arguments:
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);
}
}
I come from a C++ background, so trying to get my head around what works and what doesn't in C#
Upvotes: 2
Views: 113
Reputation: 292345
Inside the DoStuff<T>
method, the actual type of T
is unknown; your code passes int
s to the function, assuming that T
is int
, but T
could actually be anything, like string
, so you would be passing int
s to a function that accepts only string
s.
RE "I come from a C++ background, so trying to get my head around what works and what doesn't in C#":
C# generics look similar to C++ templates, but they're actually quite different.
In C++, templates are instantiated at compile time based on usage; if you use the template method with 3 different types for T, the compiler will generate 3 different methods. The body of the template method doesn't have to be valid for any T
, as long as it's valid for the actual usage cases. (sorry if my explanation isn't perfectly accurate; I don't know C++ very well)
In C#, there is no compile-time generation based on usage; the compiler only generates 1 generic method, and the actual runtime method for a given T
is generated by the runtime. To ensure this will work, the C# compiler must ensure that the method body will be valid for any T
(or if you specified constraints for T
, any T
that matches the constraints). That's why you're getting an error in your first snippet: the body of the generic method would only be valid if T
were int
.
I suggest you read the answers to this question for a more detailed explanation.
Upvotes: 8
Reputation: 23324
No need to use generics here. Change
static void DoStuff<T>(Func<T, T, T> fn)
to
static void DoStuff(Func<int, int, int> fn)
Upvotes: 1