为什么dynamic.ToString()在字符串而不是字符串之间返回一些东西?

我使用从DynamicObject派生的类型作为某些字符串的构建器。 最后,我调用ToString来获得最终结果。

在这一点上,我认为它会给我一个正常的字符串,但这个字符串有点奇怪。 当我在其上使用字符串函数时,它的行为就像一个,但它的行为就像我实际上不知道什么,既不是字符串也不是动态。


这就是我在构建器上实现ToString

 public class Example : DynamicObject { public override bool TryConvert(ConvertBinder binder, out object result) { if (binder.ReturnType == typeof(string)) { result = ToString(); return true; } result = null; return false; } public override string ToString() { return base.ToString(); } } 

当我像这样运行它

 dynamic example = new Example(); Console.WriteLine(example.ToString().ToUpper()); 

结果是正确的: USERQUERY+EXAMPLE (在LINQPad中执行时)

但是,如果我像这样打电话给第二行

 Console.WriteLine(example.ToString().Extension()); 

哪里

 static class Extensions { public static string Extension(this string str) { return str.ToUpper(); } } 

应用程序崩溃与RuntimeBinderException

‘string’不包含’Extension’的定义

但是如果我投出结果它再次起作用

 Console.WriteLine(((string)example.ToString()).Extension()); 

也许还有一个例子。

 Console.WriteLine((string)example); // UserQuery+Example 

 Console.WriteLine(example); // DynamicObject UserQuery+Example 

实际上,在将它转换为字符串之前,你永远不能确定你会得到什么。


为什么会发生这种情况,有没有办法避免额外的演员表,并以某种方式得到一个真正的字符串?

这是因为调用dynamicToString是为了返回dynamic而不是string

 dynamic example = new Example(); // test will be typed as dynamic var test = example.ToString(); 

当您在test时调用ToUpper时,它将使用动态绑定并在运行时解析为string.ToUpper 。 您必须转换为具体类型以逃避动态类型。

扩展方法是编译时function,因此dynamic类型不支持扩展方法 。 您仍然可以使用常规静态方法调用语法来调用它。

 Extensions.Extension(example.ToString()); 

但是再次 – example.ToString()将返回dynamic并且类型绑定将在运行时发生,以检查它是否可以用作Extensions.Extension调用的参数。 请查看此答案以获取详细信