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#
Inside the DoStuff<T> method, the actual type of T is unknown; your code passes ints to the function, assuming that T is int, but T could actually be anything, like string, so you would be passing ints to a function that accepts only strings.
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.
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With