我有一个接受dynamic参数的方法,在另一个参数上也有[CallerMemberName]。只要动态对象也在参数中,[CallerMemberName]参数就不会被填充。
这是CallerMemberName中的一个bug还是C#本身中的一个bug?测试见下文
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和LinqPad中进行测试,结果相同。有办法绕过这事吗?我需要对对象执行dynamic操作,所以转换到object中是行不通的。
发布于 2014-07-24 17:26:14
这是CallerMemberName中的一个bug还是C#本身中的一个bug?
不,假设有错误,那就是错误。
C# CallerMemberName没有在args中使用动态?
是这样的。那是故意的。这不是窃听器。
CallerMemberName是如何工作的?
CallerMemberName使用相同的机制作为可选参数;如果您不理解这些机制,那么第一步就是理解它们。见我关于这一主题的文章:
http://ericlippert.com/tag/optional-arguments/
在你继续之前先读一读。
.
好的,既然您了解了可选参数是编译器在调用站点插入的常量,现在应该更容易理解调用方属性是如何工作的。它们是可选的参数,被替换为“常量”,即调用站点的位置。
现在想想“动态”是如何工作的。"Dynamic“的意思是”在编译时放弃分析,在运行时再次启动编译器;确定如果编译器知道编译时的运行时类型,编译器会做什么,并生成新的代码,就像编译器生成的那样“。编译器如何知道如何将当前位置作为常量持久化到调用站点?,它需要这样做的事实是通过编译时重载解析发现的,您刚刚关闭了。
在运行时运行的编译器没有关于原始调用在源代码中的位置的信息;该信息不会持久化到调用站点,因为原始编译时编译器没有理由相信它需要这样做。
这也是为什么不能动态地分派扩展方法的原因:调用站点有效负载不包括调用点上“作用域中”的所有静态类。
不幸的是,这只是您为完全动态调度而支付的价格之一。
发布于 2014-07-24 17:04:01
正如sbat所提到的,您的方法分派是动态发生的,因为您已经将myDyn声明为dynamic。但是,在调用DynamicArgumentMethod时实际上不需要动态调度来将dynObject视为dynamic。
如果我没弄错的话,这应该管用:
var myDyn = new object();
DynamicArgumentMethod(myDyn);https://stackoverflow.com/questions/24939677
复制相似问题