It's part curiosity and part because I was just trying to use this. If you have the following definitions, this is not allowed by the compiler because it says that the member is already defined. What's the reasoning behind not allowing exclusive overloads of generic type parameters?
void Get<T>() where T: struct {}
void Get<T>() where T: class {}
It seems to me that there's no inherent problem with this. One might argue that it is not always clear which the compiler should choose in cases where the definitions overlap (but a common resolution seems to be most specific match first).
Can someone help me understand or point to a resource what the reasoning is behind disallowing this?
A generic method can also be overloaded by nongeneric methods. When the compiler encounters a method call, it searches for the method declaration that best matches the method name and the argument types specified in the call—an error occurs if two or more overloaded methods both could be considered best ...
Correct Option: C. Cannot Overload a Method Where the Formal Parameter Types of Each Overload Erase to the Same Raw Type.
The where clause in a generic definition specifies constraints on the types that are used as arguments for type parameters in a generic type, method, delegate, or local function. Constraints can specify interfaces, base classes, or require a generic type to be a reference, value, or unmanaged type.
You can also use more than one type parameter in generics in Java, you just need to pass specify another type parameter in the angle brackets separated by comma.
Eric Lippert already answered this one, in a blog post on generic constraints and method signatures: http://blogs.msdn.com/b/ericlippert/archive/2009/12/10/constraints-are-not-part-of-the-signature.aspx
Constraints on generic types are not part of method signatures in the CLR, therefore you can't have two methods that differ only in generic type constraints. Without CLR support it would be quite fiddly to get C# to support these in a sensible fashion that is compatible with other .NET languages.
The struct
constraint on Nullable<T>
is IMHO really unfortunate. Something like a Nullable<String>
or a Nullable<Nullable<Nullable<int>>>
might be have wasteful, but so what? Box the former as its content; unbox it as its content and set the HasValue
if the content is non-null. Box the former as an int
if all of the nullables report HasValue
, and when unboxing, set HasValue
of all nested items if the content was non-null.
Otherwise, I would suggest that you create a static generic class with type parameter T
which contains a delegate property that accepts a T
as a parameter. The property should return the content of a private field which should be initialized to point to a method that will check the type of T
and set the delegate to either the struct
or class
version as appropriate.
Here's a sample of what I'm talking about; this one uses various interface constraints rather than struct/class constraints, but the same principles can be used just as effectively.
static class _FooDispatcher<T> { public static Action<T> Foo = setupFoo; static void doFooWithIGoodFoo<TT>(TT param) where TT : IGoodFoo { Console.WriteLine("Dispatching as IGoodFoo with {1} type {0}", typeof(TT).ToString(), typeof(TT).IsValueType ? "value" : "reference"); param.Foo(); } static void doFooWithIOkayFoo<TT>(TT param) where TT : IOkayFoo { Console.WriteLine("Dispatching as IOkayFoo with {1} type {0}", typeof(TT).ToString(), typeof(TT).IsValueType ? "value" : "reference"); param.Foo(); } static void doFooSomehow<TT>(TT param) { Console.WriteLine("Nothing exciting with {1} type {0}", typeof(TT).ToString(), typeof(TT).IsValueType ? "value" : "reference"); } static void setupFoo(T param) { System.Reflection.MethodInfo mi; if (typeof(IGoodFoo).IsAssignableFrom(typeof(T))) mi = typeof(_FooDispatcher<T>).GetMethod("doFooWithIGoodFoo", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static); else if (typeof(IOkayFoo).IsAssignableFrom(typeof(T))) mi = typeof(_FooDispatcher<T>).GetMethod("doFooWithIOkayFoo", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static); else mi = typeof(_FooDispatcher<T>).GetMethod("doFooSomehow", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static); Foo = (Action<T>)(@Delegate.CreateDelegate(typeof(Action<T>), mi.MakeGenericMethod(typeof(T)))); Foo(param); } }
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