Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does compiler infer var to be dynamic instead of concrete type? [duplicate]

Tags:

c#

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.

like image 870
Alex Avatar asked Oct 02 '17 14:10

Alex


People also ask

What is the difference between VAR object and dynamic types?

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.

What is difference between VAR and dynamic in C#?

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.

What is the advantage of using var in C#?

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.

Is it good practice to use var in C#?

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.


2 Answers

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
like image 107
15ee8f99-57ff-4f92-890c-b56153 Avatar answered Nov 14 '22 21:11

15ee8f99-57ff-4f92-890c-b56153


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.

like image 29
Henk Holterman Avatar answered Nov 14 '22 21:11

Henk Holterman