Open instance delegate to generic interface method does not work - by naasking

Status : 

  Won't Fix<br /><br />
		Due to several factors the product team decided to focus its efforts on other items.<br /><br />
		A more detailed explanation for the resolution of this particular item may have been provided in the comments section.


3
1
Sign in
to vote
ID 685053 Comments
Status Closed Workarounds
Type Bug Repros 1
Opened 8/22/2011 8:01:45 AM
Access Restriction Public
Moderator Decision Sent to Engineering Team for consideration

Description

It is impossible to create an open instance delegate to a generic interface method. Delegate.CreateDelegate fails with NotSupportedException. Non-generic interface methods work, generic class methods work, but not generic interface methods.
Sign in to post a comment.
Posted by weaaddar on 9/12/2011 at 9:05 AM
Unusually, the calli instruction seems to support this behavior.
        public class Example
        {
            public virtual void GenericMethod<T>()
            {
                Console.WriteLine(typeof(T));
            }
        }
        public class Example2: Example
        {
            public override void GenericMethod<T>()
            {
                Console.WriteLine("Override");
                base.GenericMethod<T>();
            }
        }
        public static IntPtr RetIntPtr()
        {
            return typeof(Example).GetMethod("GenericMethod").MakeGenericMethod(new[] { typeof(int) }).MethodHandle.GetFunctionPointer();
        }

        static void Main()
        {
            var typeBuilder = TypeHelper.CreateDynamicClass("ActionCalli");
            var methodBuilder = typeBuilder.DefineMethod("Invoke", MethodAttributes.Public | MethodAttributes.Static,
                                                         CallingConventions.Standard, typeof(void),
                                                         new[] { typeof(Example) });
            var ilgen = methodBuilder.GetILGenerator();
            ilgen.Emit(OpCodes.Ldarg_0);
            ilgen.Emit(OpCodes.Call, typeof(Program).GetMethod("RetIntPtr"));
            var sigHelper = SignatureHelper.GetMethodSigHelper(CallingConventions.Standard, typeof(void));
            sigHelper.AddArgument(typeof(Example));
            ilgen.Emit(OpCodes.Calli, sigHelper);
            ilgen.Emit(OpCodes.Ret);
            var type = typeBuilder.CreateType();
            type.GetMethod("Invoke").Invoke(null, new[] { new Example() });
            type.GetMethod("Invoke").Invoke(null, new[] { new Example2()});
        }

However it does so by ignoring the virtual dispatch as displayed above.
Posted by naasking on 9/9/2011 at 4:55 PM
Thanks for the confirmation Weitao. I'm still not exactly clear *why* non-generic virtual dispatches can be so trivially resolved, but generic ones cannot. Presumably open delegates are simple stubs which simply load the provided target vtable and dispatch to the method provided (probably via an indirect jmp). This reuses all the existing dispatch logic used everywhere else in the CLR, so the absence of this one case just puzzles me.
Posted by David A Nelson on 9/9/2011 at 11:31 AM
Weitao,

Is this limitation documented anywhere? The extensive remarks and examples for Delegate.CreateDelegate (http://msdn.microsoft.com/en-us/library/74x8f551.aspx) don't seem to say anything about it.
Posted by Microsoft on 9/9/2011 at 10:44 AM
Thanks for reporting this issue. Open instance delegate to generic virtual methods (not just interface methods) are currently not supported. Because the delegate is open, we cannot resolve the target method at delegate cosntruction time. Our invocation time dispatching currently cannot handle the combination of virtual dispatching and generic instantiation.

Unfortunately, we are unable to add the support for open instance delegates on generic virtual methods in the current version of the .Net Framework. We are however, keeping the bug so that we can consider it in a future version of the product. Thank you for using Visual Studio and the .Net Framework!

Weitao Su
Microsoft Corp.
Posted by naasking on 8/25/2011 at 8:08 PM
David is correct. I had an open stackoverflow question [1] that covers the various open/closed, generic/non-generic cases before I convinced myself this was a bug worth submitting. As my bug says, open instance delegates to generic *class* methods work, as do open instance delegates to non-generic interfaces, but not open delegates to generic interface methods.

[1] http://stackoverflow.com/questions/7136615/open-delegate-for-generic-interface-method
Posted by David A Nelson on 8/23/2011 at 12:10 PM
@Viorel_

Your code creates a closed delegate, a delegate that targets an instance method on a specific instance. The OP wants to create an open delegate, a delegate that targets an instance method WITHOUT specifying an instance. This should be supported, but appears to fail when targeting generic interfaces.
Posted by MS-Moderator08 [Feedback Moderator] on 8/22/2011 at 8:17 PM
Thank you for submitting feedback on Visual Studio 2010 and .NET Framework. Your issue has been routed to the appropriate VS development team for investigation. We will contact you if we require any additional information.
Posted by Viorel_ on 8/22/2011 at 10:38 AM
Consider a different sequence:

    var bar = typeof(IFoo).GetMethod("Bar").MakeGenericMethod(typeof(int));
    var f = new Foo();
    var x = Delegate.CreateDelegate(typeof(Action<int>), f, bar);

Posted by MS-Moderator01 on 8/22/2011 at 8:40 AM
Thank you for your feedback, we are currently reviewing the issue you have submitted. If this issue is urgent, please contact support directly(http://support.microsoft.com)