Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
303 views
in Technique[技术] by (71.8m points)

c# - Why does dynamic.ToString() return something between a string and not a string?

I use a type derived from a DynamicObject as a builder for some strings. At the end I call ToString to get the final result.

At this point I thought it would give me a normal string but this string is somehow strange. It behaves like one when I use string functions on it but it behaves like I don't know actually what, something neither a string nor a dynamic.


This is how I implemented ToString on my builder

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();
    }
}

When I run it like this

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

the result is correct: USERQUERY+EXAMPLE (when executed in LINQPad)

However if I call the second line like this

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

where

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

the application crashes with a RuntimeBinderException saying

'string' does not contain a definition for 'Extension'

but if I cast the result it works again

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

Maybe one more example.

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

but

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

You can actually never be sure what you'll get until you cast it to string.


Why is this happening and is there a way to avoid the additional cast and get somehow a real string?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

That's because ToString called on dynamic is typed to return dynamic and not string:

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

When you call ToUpper on test it will use dynamic binding and resolve to string.ToUpper at runtime. You have to cast to a concrete type to escape dynamic typing.

Extension methods is a compile-time feature and as such is not supported by dynamic typing as extension method. You can still call it using regular static method invocation syntax.

Extensions.Extension(example.ToString());

But again - example.ToString() will return dynamic and type binding will happen at runtime to check if it can be used as a parameter to Extensions.Extension call. Check this answer for details.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...