25

In C#, please does anyone know why I can't do the following? (specifically the line marked 'NOT fine!' below)

interface A
{
    void Add(dynamic entity);
}

interface B : A {}

class C : B
{
    public void Add(dynamic entity)
    {
        System.Console.WriteLine(entity);
    }
}

class Program
{
    static void Main(string[] args)
    {
        B b = new C();
        dynamic x = 23;
        b.Add(23);        // fine
        b.Add((int)x);    // fine
        (b as A).Add(x);  // fine
        //b.Add(x);       // NOT fine!
    }
}

I have absolutely no problems if the call isn't dynamically-bound, or if I explicitly cast to the interface at the root of the hierarchy, but the dynamically-bound call gives me:

Unhandled Exception: Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: No overload for method 'Add' takes '1' arguments
   at CallSite.Target(Closure , CallSite , B , Object )
   at System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid2[T0,T1](CallSite site, T0 arg0, T1 arg1)
   at Program.Main(String[] args) in C:\Users\Stuart\Documents\Visual Studio 2010\Projects\CSharp Testbed\Program.cs:line 218
8
  • 1
    By the way, the last call fails even without a diamond inheritance. Commented Mar 10, 2012 at 18:33
  • @YuriyGuts: So much for a minimal compileable example eh? :) Ok, simplifying the question in that case. Commented Mar 10, 2012 at 18:37
  • 1
    +1 - It might also be good to note that b.Add((int)x) works. Commented Mar 10, 2012 at 19:08
  • 1
    This might be because of performance. If this where possible the run-time should always check out all interfaces that are implemented by the class or interface just to see if there are better matches for the call. normally most of this work will be done during compile. Commented Mar 10, 2012 at 19:39
  • 1
    Looking on Microsoft Connect it's filed as a bug - Dynamic runtime fails to find method from a base interface during runtime Commented Mar 10, 2012 at 20:56

2 Answers 2

12

Looking on Microsoft Connect it's filed as a bug - Dynamic runtime fails to find method from a base interface during runtime

Sign up to request clarification or add additional context in comments.

Comments

0

It looks like the multiple layers of interface inheritance are doing in the passing of a dynamic type variable. It's definitely tripping up the run time binding.

At this point if you're looking to get it to work a possible workaround is:

dynamic x = 23;
b.Add((object)x);

dynamic y = "Hello, World!";
b.Add((object)y);

Since dynamic is seen as object by the IL, so casting everything explicitly to type object will get this to work for you.

4 Comments

To the intermediate code, type dynamic is really just seen as type object. So, for this case at least, cast the dynamic as type object because the two are functionally equivalent for what the OP is trying to do.
The question isn't about how to make it work, the question is why doesn't it work.
@oleksii: Although I was initially surprised by this, it does actually seem to work (even when I change C.Add to do something more interesting with entity). My understanding is that the cast to object forces the binding to be done at compile-time, but that within the function entity is still dynamically-typed. So this is yet another way of making the call statically-bound -> the case for which I said "I have absolutely no problems". Unfortunately, it still doesn't explain why I have problems in the dynamic-binding case.
@BradRem: Thanks for the additional workaround. I'm still curious as to what the problem is though.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.