【发布时间】:2013-02-26 14:53:16
【问题描述】:
我刚刚遇到了最奇怪的事情,我现在有点mind = 吹......
以下程序可以正常编译,但是当您运行它时,当您尝试读取Value 时会得到RuntimeBinderException。 'object' does not contain a definition for 'Value'
class Program
{
interface IContainer
{
int Value { get; }
}
class Factory
{
class Empty : IContainer
{
public int Value
{
get { return 0; }
}
}
static IContainer nullObj = new Empty();
public IContainer GetContainer()
{
return nullObj;
}
}
static void Main(string[] args)
{
dynamic factory = new Factory();
dynamic container = factory.GetContainer();
var num0 = container.Value; // WTF!? RuntimeBinderException, really?
}
}
这是令人兴奋的部分。将嵌套类型 Factory+Empty 移到 Factory 类之外,如下所示:
class Empty : IContainer
{
public int Value
{
get { return 0; }
}
}
class Factory...
程序运行良好,有人愿意解释这是为什么吗?
编辑
在我的编码冒险中,我当然做了一些我应该首先考虑的事情。这就是为什么你看到我对私有类和内部类之间的区别有点漫不经心。这是因为我设置了 InternalsVisibleToAttribute,这使我的测试项目(在本例中消耗了这些位)的行为方式与它们的行为方式相同,这完全是设计使然,尽管从一开始就暗示了我。
阅读 Eric Lippert 的回答以获得对其余部分的良好解释。
真正让我感到警惕的是,动态绑定器考虑到了实例类型的可见性。我有大量的 JavaScript 经验,作为一名真正没有公共或私有之类的 JavaScript 程序员,我完全被可见性很重要的事实所愚弄,我的意思是毕竟,我访问这个成员就像它属于公共接口类型(我认为 dynamic 只是反射的语法糖),但动态绑定器不能做出这样的假设,除非你给它一个提示,使用简单的强制转换。
【问题讨论】:
-
如果它是
public class Empty : IContainer怎么办,否则它不只是工厂类的私有吗?可能是为什么它找不到要绑定的实现类。 -
让你的班级为空公开
-
看这里:Dynamic Gotchas。
-
我猜@Fuex 想要说明的是,在某些情况下你可以用动态做“更少”的事情。 Array.Count 说明了这一点,即使问题不同。无论如何,使用动态访问私有类的内部类是一个陷阱恕我直言。如果没有接口,它仍然会很有趣,只有 Empty 和 Value 是内部的。
-
奇怪的行为是正确的。我不在公共汽车上的时候会写一个解释。