C#CallerMemberName在args中不能使用动态?

时间:2014-07-24 16:54:20

标签: c# dynamic

我有一个接受dynamic参数的方法,并且在不同的参数上也有[CallerMemberName]。只要动态对象也在参数中,就不会填充[CallerMemberName]参数。

这是CallerMemberName还是C#本身的错误?请参阅下面的测试

    static void Main(string[] args)
    {
        new CMNTest().BaseMethod();
    }

    public void BaseMethod()
    {
        NormalMethod();
        dynamic myDyn = new Object();
        DynamicArgumentMethod(myDyn);
        ObjectArgumentMethod(new object());
        ObjectArgumentMethod((object)myDyn);
    }

    public void NormalMethod([CallerMemberName]string methodName = null)
    {
        Console.WriteLine(methodName);
    }

    public void DynamicArgumentMethod(dynamic dynObject, [CallerMemberName]string methodName = null)
    {
        Console.WriteLine(methodName);
    }

    public void ObjectArgumentMethod(object otherArg, [CallerMemberName]string methodName = null)
    {
        Console.WriteLine(methodName);
    }

输出:

BaseMethod
<null>
BaseMethod
BaseMethod

在Visual Studio和LinqPad中测试,结果相同。有什么方法吗?我需要对该对象进行dynamic项操作,因此投射到object将无效。

2 个答案:

答案 0 :(得分:11)

  

这是CallerMemberName还是C#本身的错误?

没有;假设存在一个错误就是错误。

  

C#CallerMemberName在args中不能使用动态?

那是对的。这是设计的。这不是一个错误。

  

CallerMemberName如何运作?

CallerMemberName使用与可选参数相同的机制;如果你不理解这些机制,那么第一步就是理解它们。请参阅我关于此主题的文章:

http://ericlippert.com/tag/optional-arguments/

在继续之前阅读这些内容。

.....

好了,现在您已经了解可选参数是常量,这些常量是由编译器在调用站点插入的,现在应该更容易理解调用者属性的方式工作。它们是可选参数,用&#34;常量&#34;替换。这是呼叫站点的位置。

现在想想&#34;动态&#34;作品。 &#34;动态&#34;意味着&#34;在编译时放弃分析并在运行时再次启动编译器;确定编译器将完成什么让它在编译时知道运行时类型,并生成新的代码,就像编译器生成的那样#34;。 编译器如何知道将当前位置作为常量保留在调用站点中?需要这样做的事实是通过编译时重载解析发现的,您刚刚关闭

在运行时运行的编译器没有关于源代码在原始调用中的位置的信息;该信息不会持久存储到调用站点中,因为原始编译时编译器没有理由相信它需要这样做。

这就是为什么无法动态调度扩展方法的原因:调用站点有效负载不包括范围内的所有静态类&#34;在通话时。

不幸的是,这只是您为完全动态调度支付的价格之一。

答案 1 :(得分:4)

正如sbat所提到的,您的方法调度是动态发生的,因为您已将myDyn声明为dynamic。但是,在调用DynamicArgumentMethod时,您实际上不需要动态调度,以便将dynObject视为dynamic

如果我没弄错的话,这应该有效:

var myDyn = new object();
DynamicArgumentMethod(myDyn);