C#混淆隐式类型变量与动态
如果运行TestClass.Test(),将获得RuntimeBinderException。这一切都始于C#混淆隐式类型变量与动态,c#,dynamic,implicit-typing,C#,Dynamic,Implicit Typing,如果运行TestClass.Test(),将获得RuntimeBinderException。这一切都始于var str=DoSomething(obj)隐式键入动态而不是字符串。有人能解释一下这里发生了什么吗?为什么需要字符串(str)工作?我知道你不能在动态对象上调用扩展方法,但这整件事让我觉得有点肮脏和破碎。尽管存在明显的类型不匹配,但它仍然可以正常编译,然后在运行时失败 public static class ExtensionTest { public static strin
var str=DoSomething(obj)代码>隐式键入动态而不是字符串。有人能解释一下这里发生了什么吗?为什么需要字符串(str)代码>工作?我知道你不能在动态对象上调用扩展方法,但这整件事让我觉得有点肮脏和破碎。尽管存在明显的类型不匹配,但它仍然可以正常编译,然后在运行时失败
public static class ExtensionTest
{
public static string ToJsonTest(this object x)
{
return string.Empty;
}
}
public static class TestClass
{
public static void Test()
{
dynamic obj = new ExpandoObject();
obj.var1 = "hello";
var str = DoSomething(obj);
var testObj = RequiresString(str);
var json = testObj.ToJsonTest();
}
public static string DoSomething(object x)
{
return string.Empty;
}
public static TestObj RequiresString(string x)
{
return new TestObj();
}
public class TestObj
{
public int Prop1 { get; set; }
}
}
对requireString
的调用包含dynamic
参数,因此它在运行时使用实际参数的类型进行解析。DoSomething
返回的实际类型是string
,因此运行时绑定器查找requirestring(string)
,可以成功找到TestClass.requirestring
。到目前为止,一切顺利
正如您已经提到的,下一次调用testObj.ToJsonTest()
失败,因为dynamic
上的扩展方法是目标,所以下一次调用失败
是的,它可能感觉有点脏,因为当涉及dynamic
s时,(几乎)没有编译时检查,非常像弱类型脚本语言。这就是为什么我建议只在真正需要的情况下,在尽可能狭窄的范围内使用dynamic
;特别是,我要说的是,不应该在类的公共表面上看到动态。它是脏的&我不确定这是否完全回答了你的问题,但这里有一个讨论扩展方法在CLR中如何工作以及为什么它们不与DLR一起工作的简介:对任何其他人来说,都要明确修改“str”的声明上面的显式类型解决了这个问题,即:string str=DoSomething(obj)。以防万一有人得出结论,动态是无用的——在这种情况下,不要使用“var”声明变量。让我困惑的是,为什么DoSomething()返回字符串实际上可以解释为返回动态。没有。它接受一个对象并返回一个字符串。但是由于某种原因,返回类型发生了变化。只定义了一个DoSomething(),它返回一个字符串,而不是动态字符串。仅仅将一个动态对象传递给一个函数,该函数期望一个对象以某种方式神奇而有效地改变函数的返回类型。是否正在编译某些DoSomething`1()?这对我来说仍然是胡说八道。@jeromeyers:好吧,总是有可能有多个重载具有不同的返回类型。在这种情况下,我们无法预测实际类型,因此必须是动态的。如果结果的类型取决于重载的数量,那就很奇怪了。顺便说一句,这个调用可能会返回一个更具体的类型,因此动态调用它可能会导致在下一个调用中选择其他重载。@jeromeyers:Eric Lippert有一篇关于这个的好文章:很好的文章-正是需要的。非常感谢。