I have public functions:
public static T Get<T>(this Mango m, T defaultValue = default(T)) where T : class {
Basically, I want to individually process reference types and types with a null value. It compiles; until I call the value types. For reference types, it compiles.
mango.Get<string>(); // compiles.. mango.Get(""); // compiles.. mango.Get<int>(); // The type 'int' must be a reference type in order to use it as // parameter 'T' in the generic type or method Get<T>(Mango, T) //also // The call is ambiguous between the following methods or properties: // Get<int>(Mango, int) and Get<int>(Mango, int?)
What is the real ambiguity here? When T is int , can it properly cause an overload of the structure? Also:
mango.Get<int>(0); // The type 'int' must be a reference type in order to use it as // parameter 'T' in the generic type or method Get<T>(Mango, T)
Why does the compiler only detect overload of the reference type? I tried to have two separate overloads:
public static T Get<T>(this Mango m) where T : class { return default(T); } public static T? Get<T>(this Mango m) where T : struct { return default(T); } public static T Get<T>(this Mango m, T def) where T : class { return default(T); } public static T? Get<T>(this Mango m, T? def) where T : struct { return default(T); }
The problem continued. And, obviously, the first two methods are not compiled here, since overloading does not work only on the basis of restrictions.
I tried to remove class limited overload and keep only struct limited, for example:
public static T? Get<T>(this Mango m, T? defaultValue = default(T?)) where T : struct {
Am I left with only renaming two functions? I believe that it needs to have a unified name so that the calling user simply does not worry about implementation details, but simply calls Get for any type.
Update: Marc's solution does not work if I need to avoid an optional parameter.
mango.Get<int>();
But there is more magic: (: (
public static bool IsIt<T>(this T? obj) where T : struct { return who knows; } public static bool IsIt<T>(this T obj) where T : class { return perhaps; }
By all means, I expect the same compiler error (for me) to annoy me. But this time it does not work.
Guid? g = null; g.IsIt(); //just fine, and calls the struct constrained overload "abcd".IsIt(); //just fine, and calls the class constrained overload
So, if overload resolution occurs before checking the restrictions, as Mark says, should I not get the same error this time? But no. Why is this so? What the hell is going on ?: X