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

t3c*_*b0t 5 c# dynamic tostring

我使用从a派生的类型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();
    }
}
Run Code Online (Sandbox Code Playgroud)

当我像这样运行它

dynamic example = new Example();
Console.WriteLine(example.ToString().ToUpper());
Run Code Online (Sandbox Code Playgroud)

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

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

Console.WriteLine(example.ToString().Extension());
Run Code Online (Sandbox Code Playgroud)

哪里

static class Extensions
{
    public static string Extension(this string str)
    {
        return str.ToUpper();
    }
}
Run Code Online (Sandbox Code Playgroud)

应用程序崩溃了一个RuntimeBinderException说法

'string'不包含'Extension'的定义

但如果我把结果再次投入使用

Console.WriteLine(((string)example.ToString()).Extension());
Run Code Online (Sandbox Code Playgroud)

也许还有一个例子.

Console.WriteLine((string)example); // UserQuery+Example
Run Code Online (Sandbox Code Playgroud)

Console.WriteLine(example); // DynamicObject UserQuery+Example 
Run Code Online (Sandbox Code Playgroud)

实际上,在将其转换为字符串之前,您永远无法确定您将获得什么.


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

Mar*_*zek 7

这是因为ToString被打电话dynamic的类型是返回dynamic而不是string:

dynamic example = new Example();
// test will be typed as dynamic
var test = example.ToString();
Run Code Online (Sandbox Code Playgroud)

当你调用ToUppertest它将使用动态绑定和解决string.ToUpper在运行时.您必须转换为具体类型以逃避动态类型.

扩展方法是编译时功能,因此不能通过dynamic键入扩展方法来支持.您仍然可以使用常规静态方法调用语法来调用它.

Extensions.Extension(example.ToString());
Run Code Online (Sandbox Code Playgroud)

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