When I use a method with a generic parameter to create another object, the generic object isn't selecting the most specific constructor. That sounds confusing, so here's some sample code to demonstrate what I mean...
Can anyone explain why the output of this program is:
guid <-- easy - no problem here
object <-- WHY? This should also be "guid"?!
...and how to make the generic Add<T>
function call the correct constructor of C
?? Here's the code:
void Main()
{
B b = new B();
C c = new C(Guid.Empty);
b.Add<Guid>(Guid.Empty);
}
public class B
{
List<C> cs = new List<C>();
public void Add<T>(T v) { cs.Add(new C(v)); }
}
public class C
{
public C(Guid c) { Console.WriteLine("guid"); }
public C(object c) { Console.WriteLine("object"); }
}
Explanation: Generic methods are methods that introduce their own type parameters. This is similar to declaring a generic type, but the type parameter scope is limited to the method where it is declared. Static and non-static generic methods are allowed, as well as generic class constructors.
From the point of view of reflection, the difference between a generic type and an ordinary type is that a generic type has associated with it a set of type parameters (if it is a generic type definition) or type arguments (if it is a constructed type). A generic method differs from an ordinary method in the same way.
Generic MethodsAll generic method declarations have a type parameter section delimited by angle brackets (< and >) that precedes the method's return type ( < E > in the next example). Each type parameter section contains one or more type parameters separated by commas.
Which of these is a correct way of defining generic method? Explanation: The syntax for a generic method includes a type parameter, inside angle brackets, and appears before the method's return type. For static generic methods, the type parameter section must appear before the method's return type. 9.
Overload resolution is done at compile time, not at runtime. So when you call new C(v)
from the Add<T>
method, the compiler doesn't know that T
will actually be Guid
, so it uses the only overload that is guaranteed to be compatible, which is public C(object c)
Generics in C# do not work the same as C++ templates - they are not expanded at compile time based on the usage. A single method is created and the methods called from within it are resolved statically.
Therefore, within Add
, v
can be any type, so the only thing known about it is that inherits from object
so the object
constructor for C
is the only candidate.
To get the behaviour you want you'll have to add another overload of Add
e.g.
public void Add(Guid g) { cs.Add(new C(g)); }
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