Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 737
t3chb0t Avatar asked Jan 01 '17 12:01

t3chb0t


People also ask

What happens if I call a ToString () on a string?

toString() . For String values, the toString method returns the string itself (if it's a primitive) or the string that the String object wraps.

What is the difference between convert to string and ToString?

Both these methods are used to convert a value to a string. The difference is Convert. ToString() method handles null whereas the ToString() doesn't handle null in C#. In C# if you declare a string variable and if you don't assign any value to that variable, then by default that variable takes a null value.

What does ToString return in C#?

Returns a string that represents the current object.

How do you reverse ToString?

To reverse the characters of a String object, we first need to convert it to a mutable StringBuilder object. Next, we need to call the reverse() method to reverse the character sequence of the string. Finally, we can obtain the reversed string from the StringBuilder object by calling the toString() method on it.


1 Answers

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.

like image 188
MarcinJuraszek Avatar answered Nov 14 '22 22:11

MarcinJuraszek