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?
toString() . For String values, the toString method returns the string itself (if it's a primitive) or the string that the String object wraps.
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.
Returns a string that represents the current object.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With