Given this short example program:
static void Main(string[] args)
{
Console.WriteLine(Test("hello world"));
}
private static int Test(dynamic value)
{
var chars = Chars(value.ToString());
return chars.Count();
}
private static IEnumerable<char> Chars(string str)
{
return str.Distinct();
}
When run, it will produce an exception similar to:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: ''object' does not contain a definition for 'Count''
Meaning compiler chose dynamic
as a preferred type of chars
variable.
Is there any reason for it not to choose IEnumerable<char>
as a concrete type, considering dynamic is not returned from Chars
method? Just changing the type manually to IEnumerable<char>
solves the issue, but I'm wondering why is dynamic
a default value in this case?
Edit
I've probably used example which was more complex than necessary. It seems that the question asked here:
Anomaly when using 'var' and 'dynamic'
Provides more concise example and some insights as to why it works the way it does.
https://blogs.msdn.microsoft.com/ericlippert/2012/11/05/dynamic-contagion-part-one/
Describes how compiler handles dynamics.
The variables are declared using var keyword are statically typed. The variables are declared using dynamic keyword are dynamically typed. The type of the variable is decided by the compiler at compile time. The type of the variable is decided by the compiler at run time.
var is a statically typed variable. It results in a strongly typed variable, in other words the data type of these variables are inferred at compile time. This is done based on the type of value that these variables are initialized with. dynamic are dynamically typed variables.
By using “var”, you are giving full control of how a variable will be defined to someone else. You are depending on the C# compiler to determine the datatype of your local variable – not you. You are depending on the code inside the compiler – someone else's code outside of your code to determine your data type.
Using var is lazy. While var is certainly easier to type than Dictionary<int,IList> , if the variable isn't named well, you'd never know what it refers to. Using var makes it hard to know what type the underlying variable actually is.
With dynamic
, all method calls are resolved at runtime. Therefore, it declines to guess at compile time what method is actually being called when you call Chars()
, Count()
, or even ToString()
. It could be anything, returning anything. This is often called "dynamic contagion".
For all the compiler knows, somtimes value.ToString()
will return MyRandomPOCOClass
, and at runtime it'll be able to dig up some overload like Tuple<int,String> Chars(MyRandomPOCOClass x)
. Maybe next time value.ToString()
will return int
. All bets are off. dynamic
turns C# into a scripting language.
Here's an example of dynamic runtime overload behavior (here's a fiddle):
public static void Main()
{
dynamic x = "foo";
Test(x);
x = 34;
Test(x);
}
public static void Test(string s)
{
Console.WriteLine("String " + s);
}
public static void Test(int n)
{
Console.WriteLine("Int " + n);
}
Output:
String foo
Int 34
With dynamic value
, how is the compiler to know what value.ToString()
returns?
It has the same name as our familiar C# method, but it's different.
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