为什么 dynamic.ToString() return 介于字符串和非字符串之间?
Why does dynamic.ToString() return something between a string and not a string?
我使用派生自 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' does not contain a definition for 'Extension'
但如果我投射结果它再次工作
Console.WriteLine(((string)example.ToString()).Extension());
也许再举一个例子。
Console.WriteLine((string)example); // UserQuery+Example
但是
Console.WriteLine(example); // DynamicObject UserQuery+Example
在将其转换为字符串之前,您实际上永远无法确定会得到什么。
为什么会发生这种情况,有没有办法避免额外的转换并以某种方式获得 真实 字符串?
那是因为在 dynamic
上调用的 ToString
键入的是 return dynamic
而不是 string
:
dynamic example = new Example();
// test will be typed as dynamic
var test = example.ToString();
当您在 test
上调用 ToUpper
时,它将使用动态绑定并在运行时解析为 string.ToUpper
。您必须转换为具体类型才能 escape 动态类型。
扩展方法是一种编译时功能,因此 dynamic
键入 作为扩展方法 不支持。您仍然可以使用常规静态方法调用语法调用它。
Extensions.Extension(example.ToString());
但再次 - example.ToString()
将 return dynamic
并且类型绑定将在运行时发生以检查它是否可以用作 Extensions.Extension
调用的参数。检查 this answer 了解详情。
我使用派生自 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' does not contain a definition for 'Extension'
但如果我投射结果它再次工作
Console.WriteLine(((string)example.ToString()).Extension());
也许再举一个例子。
Console.WriteLine((string)example); // UserQuery+Example
但是
Console.WriteLine(example); // DynamicObject UserQuery+Example
在将其转换为字符串之前,您实际上永远无法确定会得到什么。
为什么会发生这种情况,有没有办法避免额外的转换并以某种方式获得 真实 字符串?
那是因为在 dynamic
上调用的 ToString
键入的是 return dynamic
而不是 string
:
dynamic example = new Example();
// test will be typed as dynamic
var test = example.ToString();
当您在 test
上调用 ToUpper
时,它将使用动态绑定并在运行时解析为 string.ToUpper
。您必须转换为具体类型才能 escape 动态类型。
扩展方法是一种编译时功能,因此 dynamic
键入 作为扩展方法 不支持。您仍然可以使用常规静态方法调用语法调用它。
Extensions.Extension(example.ToString());
但再次 - example.ToString()
将 return dynamic
并且类型绑定将在运行时发生以检查它是否可以用作 Extensions.Extension
调用的参数。检查 this answer 了解详情。