c# - 奇怪的 C# 动态行为

标签 c# dynamic dynamic-language-runtime

<分区>

在调查 C# 动态关键字的工作原理时,我偶然发现了一些奇怪的行为。它几乎看起来像一个错误,但更有可能是该行为的原因。

在下面的代码中,有两个调用,一个调用 obj1,一个调用 obj2,但只有一个调用正确执行。看起来局部变量类型是原因,但“Hello”也应该可以从 IDynamicTarget 访问,因为它扩展了 IDynamicTargetBase。

namespace DynamicTesting
{
    interface IDynamicTargetBase
    {
        string Hello(int a);
    }

    interface IDynamicTarget : IDynamicTargetBase
    {
    }

    class DynamicTarget : IDynamicTarget
    {
        public string Hello(int a)
        {
            return "Hello!";
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            dynamic a = 123;

            IDynamicTargetBase obj1 = new DynamicTarget();
            obj1.Hello(a);  // This works just fine

            IDynamicTarget obj2 = new DynamicTarget();
            obj2.Hello(a); // RuntimeBinderException "No overload for method 'Hello' takes '1' arguments"
        }
    }
}

最佳答案

看来是方法重载解析的问题。

只需将 dynamic a = 123 更改为 int a = 123,您的代码就可以运行了。此外,如果您将方法调用更改为 obj2.Hello((int)a);。最后,将变量键入 DynamicTarget 而不是 IDynamicTarget,它也会起作用!

为什么?当您使用动态表达式并且有多个调用具有动态参数的方法重载时,运行时将无法解析要调用的重载,因为方法重载解析基于时提供的参数的类型和顺序所谓的方法被调用了。

我的推测是,当一个接口(interface)还实现了另一个接口(interface)时,运行时重载解析会失败,并且运行时似乎明白不能保证第二个接口(interface)将定义一个也实现的其他接口(interface)的重载,它强制您在编译时提供参数的实际类型。

[...] but "Hello" should also be accesible from IDynamicTarget, because it extends IDynamicTargetBase.

它是可以访问的,但是运行时无法解析如何提供方法的参数...

关于c# - 奇怪的 C# 动态行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28135176/

相关文章:

c# - WPF - Windows Azure 样式 TabControl(?)

c# - c++\cli 项目依赖的 c++ dll 未复制到 c# 输出目录

c# - 当存在非静态、更适合的方法时,如何使用动态参数调用静态方法?

javascript - 获取被点击元素的div父元素,以获取同一个div中的p类

wcf - 使用动态语言和 DLR 创建 WCF 服务

c# - 如何使用反射找到特定的通用重载?

c# - 使用 LINQ/JavaScriptSerializer 创建 JSON 对象而不是数组

使用 Linq 表达式的 C# 动态数据库过滤

c# - DLR 返回类型

c# - DLR 的内存占用是多少?