灵感来自这个问题 https://stackoverflow.com/questions/12842712/why-does-the-c-sharp-compiler-not-fault-code-where-a-static-method-calls-an-inst我在 Mono 2.10.9 和 Visual Studio 2010 上尝试了以下代码:
public class Example
{
public static void Main()
{
Foo(1);
}
public static void Foo( dynamic x )
{
Example.Bar(x);
}
static void Bar( dynamic x )
{
x++;
}
int count;
void Bar( int x )
{
count++;
}
}
如你看到的,Foo
是静态的,所以只能访问静态的Bar
- 我明确调用静态版本!
我知道我无法声明static void Bar( int x )
,因为存在非静态版本。
但是,更改非静态的参数类型Bar
比如说,字符串,让一切都好起来。
这是为什么?这里有什么规则?静态方法可以调用吗?
也许这是 Mono DLR 问题?
编辑:为了澄清。我想知道什么规则将显式调用转变为静态方法(至少我认为这是明确的)调用非静态的?从静态上下文来看,这显然是不可能的。
或者,如果没有这样的规则,是否可以bug?这种行为可以通过某种方式避免吗?
其中的关键声明是“我知道我无法声明 static void Bar( int x ),因为存在非静态版本。”。使用dynamic关键字将重载决策推迟到运行时,但是当运行时出现时,它并不能免除您的规则。
当该过载解决方案最终发生时,DLR 会评估所有可用选项,然后选择最佳选项。在此解析时间之前,动态类型的参数的行为与对象类型非常相似(请参阅here http://msdn.microsoft.com/en-gb/library/dd264736.aspx)。因此,通常情况下,采用 int 的更具体的方法将是过载解决方案的获胜者,因此会选择采用动态/对象的方法。这意味着实例方法通常会获胜。 DLR 知道具有相同签名的两个方法不能因静态性而不同。在评估可用选项时,您期望它做的是说“啊哈!在这种情况下,static void Bar(dynamic x) 可以解释为 static void Bar(int x)”。然而,如果它确实这么说,那么就会违反关于不具有相同的静态和非静态方法的规则。它的内部选项列表将包含静态和非静态 Bar 方法,这两个方法都具有相同的签名。所以不能这么说。这就留下了唯一的其他选择,它恰好是实例方法。这在这种情况下没有用,因此 DLR 会抛出 RuntimeBinderException。如果将实例 Bar 的参数更改为 int 以外的参数,则方法签名不会冲突,因此 DLR 可以将静态动态 Bar 解释为采用 int 并选择该重载。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)