C#动态类型问题我刚刚遇到了最奇怪的事情,我有点在想=目前...下面的程序编译正常,但是当你运行它时,当你在尝试读取值时会得到一个RuntimeBinderException。“object”不包含“Value”的定义classProgram{interfaceIContainer{intValue{get;}}classFactory{classEmpty:IContainer{publicintValue{get{return0;}}}staticIContainernullObj=newEmpty();公共IContainerGetContainer(){返回nullObj;}}staticvoidMain(string[]args){dynamicfactory=newFactory();动态容器=factory.GetContainer();varnum0=container.Value;//WTF!?RuntimeBinderException,真的吗?}}这是令人兴奋的部分。将嵌套类型Factory+Empty移到Factory类之外,如下所示:classEmpty:IContainer{publicintValue{get{return0;}}}classFactory...该程序运行良好,有人愿意解释为什么会这样吗?编辑在我的编码冒险中,我确实做了一些我应该首先想到的事情。这就是为什么你看到我在私有类和内部类之间的区别。这是因为我设置了InternalsVisibleToAttribute,这使我的测试项目(在本例中消耗位)表现得像它们一样,这完全是设计使然,尽管从一开始我就暗示过。阅读EricLippert的回答以获得对其余部分的良好解释。真正引起我注意的是动态绑定器考虑了实例类型的可见性。我有很多javascript经验,作为一个javascript程序员,真的没有公共或私有这样的东西,而且我对可见性很重要这一事实感到非常困惑,我的意思是,毕竟,我正在访问这个成员作为如果它是公共接口类型(我认为动态只是反射的语法糖)但是动态绑定器不能做出这样的假设,除非你使用简单的转换给它一个提示。C#中“动态”的基本原则是:表达式在运行时进行类型分析,就像运行时类型是编译时类型一样。那么让我们看看如果我们真的这样做会发生什么:dynamicnum0=((Program.Factory.Empty)container).Value;该程序将失败,因为无法访问Empty。dynamic不允许您进行本质上非法的分析。然而,运行时分析器意识到这一点并决定作弊。它问自己“是否有可以访问的基类?”答案显然是肯定的。于是决定回到基类分析:dynamicnum0=((System.Object)container).Value;这会失败,因为程序会给你一个“对象没有名为Value的成员”的错误。这是你得到的错误。动态分析永远不会说“哦,你一定是指”dynamicnum0=((Program.IContainer)container).Value;因为当然,如果那是你的意思,那就是你无论如何都应该写的。此外,dynamic的目的是回答这个问题,如果编译器知道运行时类型会发生什么,并且转换为接口不会给你运行时类型。当你把Empty移到外面时,动态运行时分析器会假装你写了:dynamicnum0=((Empty)container).Value;现在可以访问Empty并且转换是合法的,因此您得到了预期的结果。更新:可以将此代码编译成程序集,引用此程序集,如果Empty类型在类外部,默认情况下会将其设为内部。我无法重现所描述的行为。让我们试一个例子:publicclassFactory{publicstaticThingCreate(){returnnewInternalThing();}}publicabstractclassThing{}内部类InternalThing:Thing{publicintValue{get;设置;}}>csc/t:librarybar.csclassP{staticvoidMain(){System.Console.WriteLine(((dynamic)(Factory.Create())).Value);}}>cscfoo.cs/r:bar.dll>fooUnhandledException:Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:'Thing'doesnotcontainadefinitionfor'Value'你会看到它是如何工作的:运行时活页夹检测到InternalThing是外部程序集的内部,所以它不是可在foo.exe中访问。所以它回退到公共基类型Thing,它是可访问的但没有必要的属性。我无法重现您描述的行为,如果您可以重现它,那么您就发现了一个错误。如果你有一个小错误,我会很乐意将它传递给我以前的同事。我想,在运行时,容器方法调用只是在私有Empty类中解析,这会导致代码失败。据我所知,动态不能用于访问私有成员(或私有类的公共成员)这应该(当然)有效:varnum0=((IContainer)container).Value;这是Empty类,它是私有的:因此您不能在声明类(工厂)之外操作Empty实例。这就是您的代码失败的原因。如果Empty是内部的,您可以在整个程序集中操作它的实例(好吧,不是因为Factory是私有的),允许所有动态调用,并且您的代码将工作。以上就是C#学习教程:C#动态类型问题分享的全部内容。如果对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右边联系管理员删除。如需转载请注明出处:
