Should an interface-based method invoke that uses "dynamic" still obey C# method resolution rules?
Asked Answered
D

1

17

As I understand it, each language can have it's own dynamic handler, so that the appropriate rules are applied. I'm unsure if the following is correct/incorrect; thoughts?

Scenario: two interfaces (one implements the other) with some methods:

public interface IA {
    void Bar(object o);
}
public interface IB : IA {
    void Foo(object o);
}

and a basic implementation:

public class B : IB {
    public void Foo(object o) { Console.WriteLine("Foo"); }
    public void Bar(object o) { Console.WriteLine("Bar"); }
}

Now, with normal C# (no dynamic), we can access methods of IA from a target of type IB:

IB b = new B();
var o = new { y = "z" };
b.Foo(o.y); // fine
b.Bar(o.y); // fine

Now let's deliberately add some dynamic to the arguments, which makes the entire invoke use dynamic processing (as in the general case this could impact overload resolution, although it won't here):

IB b = new B();
dynamic x = new {y = "z"};
b.Foo(x.y); // fine
b.Bar(x.y); // BOOM!

Which fails with the RuntimeBinderException:

'IB' does not contain a definition for 'Bar'

Now, what it says is entirely correct in as much as IB does not have a Bar method. However, as illustrated in the first example: under normal C# rules would expect that since the declaration type of the target is an interface (IB), the other interfaces known to be implemented (i.e. IA) are checked as part of overload resolution.

So: is this a bug? Or am I misreading it?

Dahabeah answered 23/3, 2012 at 10:19 Comment(5)
+1 Interesting. I wonder if the DLR offers lesser support for this sort of thing as opposed to the compiler/CLR. I presume the DLR is responsible for the attempted resolution of the call?Thunderous
@Adam my understanding is that for reflection-based calling, there is a language-specific provider, precisely to follow the language conventions, i.e. Microsoft.CSharp.RuntimeBinder.BinderDahabeah
Do you observe the same with class inheritance trying to call base methods? (As opposed to inherited interface methods).Thunderous
Possibly similar reading: #3072134Thunderous
@Adam yes, that is describing the same issue - I think the question is slightly different though; the intent of this question is: "is this behaviour correct". I understand what is happening, just not whether it is correct.Dahabeah
S
6

This is a well known limitation of the binder, asked about several times at SO and the subject of this feedback article. I'll quote Microsoft's answer:

This was an area we explicitly scoped out due to time when shipping C# 4.0 and we'd love to revisit this. This specific case of ISet/IList methods that are actually defined on ICollection is the most visible place where not digging up through parent interfaces unnecessarily limits the reach of dynamic binding in C#.

We hope to add such support soon, though this issue currently falls just below our bug triage cut line. We're marking the issue Won't Fix to indicate that we're not currently tracking to fix this issue in the next release of Visual Studio. We'll reactivate this bug over the next year if we get further than expected through our bug triage list, or if we revisit the bug for the following release.

Which didn't happen yet, afaik. The article doesn't have a lot of votes.

Stenotypy answered 23/3, 2012 at 12:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.