This question already has answers here:
Odd behaviour change with var, dynamic and linq combination

(3个答案)



Will the dynamic keyword in C#4 support extension methods?

(4个答案)


已关闭6年。




我在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();
    }
}

异常(exception):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中指出的那样,对于动态类型,扩展名方法在调用站点将不可用:

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

隐式声明

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

10-02 03:07