I'm a C++ developer who tries to play with C# generics. My final goal is to mimic template specialization in C#.
In other term, I want a default implementation of a function available for all types and a specific implementation for a specific type.
My first attempt was with generics and extension methods but it seems C# generics are resolved at run-time, which gives this weird result (weird for a C++ programmer at least):
//any of my classes
public class MyClass
{
}
//class extension for my classes only
public static class MyClassExt
{
public static string GetCaption(this MyClass c)
{
return "MyClass caption";
}
}
//"default" extension for all
public static class objectExt
{
public static string GetCaption(this object o)
{
return $"object caption {o}";
}
}
internal class Program
{
public static string GetCaption<T>(T t)
{
//Isn't it supposed to call MyClassExt.GetCaption if t is MyClass ?
return t.GetCaption();
}
static void Main(string[] args)
{
int i = 0;
Console.WriteLine(i.GetCaption()); //> object caption 0
Console.WriteLine(new MyClass().GetCaption()); //> MyClass caption
//calls GetCaption<T> with T is MyClass
Console.WriteLine(GetCaption(new MyClass())); //> object caption csharpconsole.MyClass
}
}
What is the usual way to handle such case in C#?
Edit:
trying to implement @Enigmativity suggestion, I've tried this with no success:
//class extension for my classes only
public static class MyClassExt
{
//My attempt for @Enigmativity suggestion
public static string GetCaption<T>(this T t) where T : MyClass
{
return "MyClass caption";
}
}
//"default" extension for all
public static class objectExt
{
public static string GetCaption(this object o)
{
return $"object caption {o}";
}
}
internal class Program
{
public static string GetCaption<T>(T t)
{
//Isn't it supposed to call MyClassExt.GetCaption if t is MyClass ?
return t.GetCaption();
}
static void Main(string[] args)
{
int i = 0;
Console.WriteLine(i.GetCaption()); //> object caption 0
Console.WriteLine(new MyClass().GetCaption()); //> MyClass caption
//calls GetCaption<T> with T is MyClass
Console.WriteLine(GetCaption(new MyClass())); //> object caption csharpconsole.MyClass
}
}
My final goal is to mimic template specialization in c#.
I think that's unlikely to end well, to be honest. Generics aren't like C++ templates; they're used to accomplish similar goals, but with quite different approaches.
My first attempt was with generics and extension methods but it seems c# generics are resolved at run-time
No, that's not true - which explains the result you're getting.
When compiling the code for GetCaption<T>
, the compiler resolves the call to t.GetCaption()
without knowing anything about T
, so the only extension method it can call is the one with the first parameter of type object
- which is what you're seeing.
Basically, you need to remember that each generic method is only compiled once - not once against each type argument. Everything flows from that understanding: you can see polymorphism in terms of overriding, as normal, but not overloading where a different method is chosen at compile-time.