【问题标题】:Should an interface-based method invoke that uses "dynamic" still obey C# method resolution rules?使用“动态”的基于接口的方法调用是否仍应遵守 C# 方法解析规则?
【发布时间】:2012-04-07 21:51:55
【问题描述】:

据我了解,每种语言都可以有自己的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.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 处理(因为在一般情况下这可能会影响重载决议,尽管它不会在这里):

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

RuntimeBinderException 失败:

“IB”不包含“酒吧”的定义

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

那么:这是一个错误吗?还是我看错了?

【问题讨论】:

  • +1 有趣。我想知道与编译器/CLR 相比,DLR 是否对这类事情提供较少的支持。我认为 DLR 负责尝试解决呼叫?
  • @Adam 我的理解是,对于基于反射的调用,有一个特定于语言的提供程序,正是为了遵循语言约定,即Microsoft.CSharp.RuntimeBinder.Binder
  • 在类继承尝试调用基方法时,您是否观察到相同的情况? (与继承的接口方法相反)。
  • 可能类似的读法:stackoverflow.com/questions/3071634/…
  • @Adam 是的,这是在描述同一个问题 - 我认为这个问题略有不同;这个问题的目的是:“这种行为是否正确”。我明白发生了什么,只是不知道它是否正确。

标签: c# dynamic


【解决方案1】:

这是一个众所周知的活页夹限制,在 SO 和 this feedback article 的主题上被问过几次。我将引用微软的回答:

由于发布 C# 4.0 的时间,这是我们明确界定的一个领域,我们很乐意重新审视这一点。在 ICollection 上实际定义的 ISet/IList 方法的这种特定情况是最明显的地方,其中不通过父接口挖掘不必要地限制了 C# 中动态绑定的范围。

我们希望尽快添加此类支持,尽管此问题目前刚好低于我们的错误分类切割线。我们将问题标记为不会修复,以表明我们目前未跟踪在 Visual Studio 的下一版本中修复此问题。如果我们通过错误分类列表获得的结果超出预期,或者如果我们在下一个版本中重新访问该错误,我们将在明年重新激活此错误。

这还没有发生,afaik。文章票数不多。

【讨论】:

    猜你喜欢
    • 2012-07-02
    • 1970-01-01
    • 2013-01-30
    • 1970-01-01
    • 1970-01-01
    • 2018-10-02
    • 2020-04-11
    • 1970-01-01
    相关资源
    最近更新 更多