下面的代码有一个静态方法Foo()
,它调用一个实例方法Bar()
:
public sealed class Example
{
int count;
public static void Foo( dynamic x )
{
Bar(x);
}
void Bar( dynamic x )
{
count++;
}
}
它编译时没有错误*,但在运行时生成运行时绑定程序异常。如预期的那样,将动态参数删除到这些方法会导致编译器错误。
那么为什么使用动态参数可以编译代码? ReSharper也不会将其显示为错误。
Edit 1: *在Visual Studio 2008中
Edit 2:添加了sealed
,因为子类可能包含静态Bar(...)
方法。当不可能在运行时调用实例方法以外的其他任何方法时,即使是密封版本也可以编译。
更新:以下答案写于2012年,在C#7.3引入之前(2018年5月)。在What's new in C# 7.3中的第[[改善的过载候选者]]部分的项目1中,说明了如何更改过载解决规则,以便尽早丢弃非静态过载。因此,以下答案(以及整个问题)目前基本上只具有历史意义!
((Pre C#7.3:)
出于某种原因,过载解析总是找到最佳匹配
之前
,检查静态与非静态。请尝试使用所有静态类型的代码:class SillyStuff
{
static void SameName(object o) { }
void SameName(string s) { }
public static void Test()
{
SameName("Hi mom");
}
}
这不会编译,因为最好的重载是采用string
的重载。但是,嘿,那是一个实例方法,因此编译器会抱怨(而不是承受次优的重载)。
添加:因此,我认为原始问题的dynamic
示例的解释是,为了保持一致,当类型为动态时,我们还
first
找到最佳的重载(仅检查参数编号和参数类型等,而不是静态与非静态),并且仅then检查静态。但这意味着静态检查必须等到运行时才能执行。因此观察到的行为。最新补充:从this blog post by Eric Lippert中可以推断出他们为什么选择做这种滑稽的事情的背景。