Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
335 views
in Technique[技术] by (71.8m points)

c# - Open delegate for generic interface method

I'm trying to create an open instance delegate for a generic interface method, but I keep receiving a NotSupportedException. Here is the simplified code that won't run:

interface IFoo
{
    void Bar<T>(T j);
}
class Foo : IFoo
{
    public void Bar<T>(T j)
    {
    }
}
static void Main(string[] args)
{
    var bar = typeof(IFoo).GetMethod("Bar").MakeGenericMethod(typeof(int));
    var x = Delegate.CreateDelegate(typeof(Action<IFoo, int>), null, bar);
}

The last line throws NotSupportedException, "Specified method is not supported". By comparison, a non-generic open instance delegate runs fine:

interface IFoo
{
    void Bar(int j);
}
class Foo : IFoo
{
    public void Bar(int j)
    {
    }
}
static void Main(string[] args)
{
    var bar = typeof(IFoo).GetMethod("Bar");
    var x = Delegate.CreateDelegate(typeof(Action<IFoo, int>), null, bar);
}

And a closed generic delegate also works:

interface IFoo
{
    void Bar<T>(T j);
}
class Foo : IFoo
{
    public void Bar<T>(T j)
    {
    }
}
static void Main(string[] args)
{
    var bar = typeof(IFoo).GetMethod("Bar").MakeGenericMethod(typeof(int));
    var x = Delegate.CreateDelegate(typeof(Action<int>), new Foo(), bar);
}

So the recipe for closed generic delegates and open instance delegates work separately, but not when combined. It's starting to look like either a runtime bug, or intentional omission. Anyone have any insight here?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This is a recap of the topic and this specific issue for those that find this question (since it seems the OP has already got his answer on Microsoft Connect).


Answer

Creating an open instance generic delegate for a generic interface method is impossible (As confirmed by Microsoft here). Currently, it is possible to implement any of the following combinations of open-instance/closed static, generic/non-generic, interface/class methods (with code samples provided at the end of the answer):

  • open instance non-generic delegate for a non-generic interface method
  • closed static generic delegate for a generic interface method
  • closed static non-generic delegate for a non-generic interface method
  • open instance generic delegate for a generic class method
  • open instance non-generic delegate for a non-generic class method
  • closed static generic delegate for a generic class method
  • closed static non-generic delegate for a non-generic class method

Usually, the best replacement for an open instance generic delegate for a generic interface method is an open instance generic delegate for a generic class method.


Code Samples

  • open instance non-generic delegate for a non-generic interface method

    interface IFoo
    {
      void Bar(int j);
    }
    
    class Foo : IFoo
    {
      public void Bar(int j)
      {
      }
    }
    
    static void Main(string[] args)
    {
      var bar = typeof(IFoo).GetMethod("Bar");
      var x = Delegate.CreateDelegate(typeof(Action<IFoo, int>), null, bar);
    }
    
  • closed static generic delegate for a generic interface method

      interface IFoo
      {
        void Bar<T>(T j);
      }
    
      class Foo : IFoo
      {
        public void Bar<T>(T j)
        {
        }
      }
    
      static void Main(string[] args)
      {
        var bar = typeof(IFoo).GetMethod("Bar").MakeGenericMethod(typeof(int));
        var x = Delegate.CreateDelegate(typeof(Action<int>), new Foo(), bar);
      }
    
  • closed static non-generic delegate for a non-generic interface method

      interface IFoo
      {
        void Bar(int j);
      }
    
      class Foo : IFoo
      {
        public void Bar(int j)
        {
        }
      }
    
      static void Main(string[] args)
      {
        var bar = typeof(IFoo).GetMethod("Bar");
        var x = Delegate.CreateDelegate(typeof(Action<int>), new Foo(), bar);
      }
    
  • open instance generic delegate for a generic class method

    class Foo
    {
        public void Bar<T>(T j)
        {
        }
    }
    
    static void Main(string[] args)
    {
        var bar = typeof(Foo).GetMethod("Bar").MakeGenericMethod(typeof(int));
        var x = Delegate.CreateDelegate(typeof(Action<Foo, int>), null, bar);
    }
    
  • open instance non-generic delegate for a non-generic class method

    class Foo
    {
        public void Bar(int j)
        {
        }
    }
    
    static void Main(string[] args)
    {
        var bar = typeof(Foo).GetMethod("Bar");
        var x = Delegate.CreateDelegate(typeof(Action<Foo, int>), null, bar);
    }
    
  • closed static generic delegate for a generic class method

    class Foo
    {
        public void Bar<T>(T j)
        {
        }
    }
    
    static void Main(string[] args)
    {
        var bar = typeof(Foo).GetMethod("Bar").MakeGenericMethod(typeof(int));
        var x = Delegate.CreateDelegate(typeof(Action<int>), new Foo(), bar);
    }
    
  • closed static non-generic delegate for a non-generic class method

    class Foo
    {
        public void Bar(int j)
        {
        }
    }
    
    static void Main(string[] args)
    {
        var bar = typeof(Foo).GetMethod("Bar");
        var x = Delegate.CreateDelegate(typeof(Action<int>), new Foo(), bar);
    }
    


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...