简体   繁体   中英

Overloading generic type parameters disallowed?

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?

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);
            }
        }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM