基于接口的方法是否应该调用使用;“动态”;仍然遵守C#方法解析规则吗?

基于接口的方法是否应该调用使用;“动态”;仍然遵守C#方法解析规则吗?,c#,dynamic,C#,Dynamic,据我所知,每种语言都可以有自己的动态处理程序,以便应用适当的规则。我不确定以下内容是否正确/不正确;想法 场景:两个接口(一个实现另一个)和一些方法: public interface IA { void Bar(object o); } public interface IB : IA { void Foo(object o); } 以及一项基本实施: public class B : IB { public void Foo(object o) { Console.

据我所知,每种语言都可以有自己的
动态
处理程序,以便应用适当的规则。我不确定以下内容是否正确/不正确;想法

场景:两个接口(一个实现另一个)和一些方法:

public interface IA {
    void Bar(object o);
}
public interface IB : IA {
    void Foo(object o);
}
以及一项基本实施:

public class B : IB {
    public void Foo(object o) { Console.WriteLine("Foo"); }
    public void Bar(object o) { Console.WriteLine("Bar"); }
}
现在,使用普通C#(无
dynamic
),我们可以从类型为
IB
的目标访问
IA
的方法:

IB b = new B();
var o = new { y = "z" };
b.Foo(o.y); // fine
b.Bar(o.y); // fine
现在,让我们故意在参数中添加一些
dynamic
,这使得整个调用使用
dynamic
处理(在一般情况下,这可能会影响重载解析,尽管这里不会):

由于运行时BinderException而失败:

“IB”不包含“Bar”的定义

现在,它所说的完全正确,因为
IB
没有
Bar
方法。但是,如第一个示例所示:在正常的C#规则下,由于目标的声明类型是接口(
IB
),因此将检查已知要实现的其他接口(即
IA
)作为过载解决方案的一部分


那么:这是一个bug吗?还是我误读了?

这是活页夹的一个众所周知的局限性,在SO和主题中被多次询问。我将引用微软的回答:

这是我们在发布C#4.0时明确指出的一个领域,我们很想再次讨论这个问题。实际上在ICollection上定义的ISet/IList方法的这种特殊情况是最明显的,不通过父接口挖掘会不必要地限制C#中动态绑定的范围

我们希望很快增加这样的支持,尽管这个问题目前刚好低于我们的缺陷分类界限。我们将此问题标记为“不会修复”,以表明我们目前没有跟踪以在下一版本的Visual Studio中修复此问题。如果我们通过错误分类列表得到了比预期的更进一步的结果,或者如果我们在下一版本中重新访问该错误,我们将在明年重新激活该错误


这还没发生,好吧。这篇文章的票数不多。

+1很有趣。我想知道DLR对这类事情的支持是否比编译器/CLR少。我认为DLR负责尝试解决呼叫?@Adam我的理解是,对于基于反射的呼叫,有一个特定于语言的提供者,严格遵守语言约定,例如,
Microsoft.CSharp.RuntimeBinder.Binder
在类继承尝试调用基方法时,您是否观察到了相同的情况?(与继承的接口方法相反)可能类似的阅读:@Adam是的,这是在描述同一个问题-我认为问题略有不同;这个问题的目的是:“这种行为正确吗?”。我理解正在发生的事情,只是不知道它是否正确。
IB b = new B();
dynamic x = new {y = "z"};
b.Foo(x.y); // fine
b.Bar(x.y); // BOOM!