c# - C# 动态中可能存在错误?

标签 c# dynamic

<分区>

我在 C# 中使用动态变量时遇到了问题。这是在编码 NancyFx 路由模块时出现的,但我已将问题归结为以下示例。虽然我在原始代码中收到了一个不同的异常,但示例代码仍然抛出一个我认为是错误的异常。有没有人看到这里发生了什么,或者其他人遇到过类似的问题?

请注意,以下帖子可能是相关的: StackOverflowException when accessing member of generic type via dynamic: .NET/C# framework bug? System.Dynamic bug?

代码:

class Program
{
    static void Main(string[] args)
    {
        var dictionary = new Dictionary<string, object>();
        dictionary.Add("number", 12);
        var result = MethodUsesExplicitDeclaration(dictionary);
        var result2 = MethodUsesImplicitDeclaration(dictionary);
    }

    static dynamic MethodUsesExplicitDeclaration(dynamic reallyDictionary)
    {
        // this works, ostensibly because the local variable is explicitly declared
        IDictionary<string, object> dictionary = CastDictionary(reallyDictionary);
        return dictionary.Get<int>("number");
    }

    static dynamic MethodUsesImplicitDeclaration(dynamic reallyDictionary)
    {
        // this throws an exception, and the only difference is 
        // that the variable declaration is implicit
        var dictionary = CastDictionary(reallyDictionary);
        return dictionary.Get<int>("number");
    }

    static IDictionary<string, object> CastDictionary(dynamic arg)
    {
        return arg as IDictionary<string, object>;
    }
}

static class Extensions
{
    public static T Get<T>(this IDictionary<string, object> dictionary, string key)
    {
        var value = dictionary[key];
        if (value is T)
            return (T)value;
        throw new InvalidOperationException();
    }
}

异常:Microsoft.CSharp.RuntimeBinder.RuntimeBinderException was unhandled HResult=-2146233088 Message='System.Collections.Generic.Dictionary<string,object>' does not contain a definition for 'Get' Source=Anonymously Hosted DynamicMethods Assembly StackTrace: at CallSite.Target(Closure , CallSite , Object , String ) at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1) at DynamicBug.Program.MethodUsesImplicitDeclaration(Object reallyDictionary) in c:\TFS\UnreleasedCode\POC\DynamicBug\DynamicBug\Program.cs:line 28 at DynamicBug.Program.Main(String[] args) in c:\TFS\UnreleasedCode\POC\DynamicBug\DynamicBug\Program.cs:line 16 InnerException:

最佳答案

问题在于,当您没有明确地将对象分配给 IDictionary<string,object> 时声明时,该对象仍将是动态类型(请参阅图像中的类型解析)。

正如 Eric Lippert 在 https://stackoverflow.com/a/5313149/1039903 中指出的那样对于动态类型,扩展方法在调用站点不可用:

To expand on Jon's answer, the reason this doesn't work is because in regular, non-dynamic code extension methods work by doing a full search of all the classes known to the compiler for a static class that has an extension method that match. The search goes in order based on the namespace nesting and available "using" directives in each namespace.

That means that in order to get a dynamic extension method invocation resolved correctly, somehow the DLR has to know at runtime what all the namespace nestings and "using" directives were in your source code. We do not have a mechanism handy for encoding all that information into the call site. We considered inventing such a mechanism, but decided that it was too high cost and produced too much schedule risk to be worth it.

我将您的代码加载到测试方法中,以向您展示 var dictionary 中实际解决的问题在运行时与显式声明相比。

显式声明:

enter image description here enter image description here

隐式声明

enter image description here enter image description here

如果您查看 dictionary 的类型解析显式声明的类型为 System.Collection.Generic.IDictionary并且隐式声明的类型为 dynamic{System.Collections.Generic.Dictionary}

关于c# - C# 动态中可能存在错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24761294/

相关文章:

javascript - 通过动态更改内容让 IE 尊重您的空白

c# - 如何调用未知路径的 .exe 文件?

c# - 文件夹中的多个图像

c# - 超过 16 字节的结构的最佳解决方案

c# - 在Windows服务中添加Trace文件

c# - LINQ Union 不同类型 - 动态转换为接口(interface)?

java - 如果数组大小先验未知,如何填充数组

c# - 为什么调用 ISet<dynamic>.Contains() 编译,但在运行时抛出异常?

jquery - 动态加载的文本不在 div 内

Android:在嵌套布局中动态添加 View