This question is for educational purposes only. I have this code that fails at compile time on line where I want to write lines to file. (File.WriteAllLines(@"C:\temp\processed.txt",contents);
)
Error messages:
Argument 2: cannot convert from
'System.Collections.Generic.List<dynamic>'
to 'string[]' C:\hg\PricingEngine\Source\App\Support\PricingEngine.Migrator\Program.cs 49 57 PricingEngine.MigratorError 6 The best overloaded method match for 'System.IO.File.WriteAllLines(string, string[])' has some invalid arguments C:\hg\PricingEngine\Source\App\Support\PricingEngine.Migrator\Program.cs 49 13 PricingEngine.Migrator
If I comment out last line and inspect with breakpoint all lines are strings, and everything works just fine.
Code:
public static void Main()
{
var t = new List<dynamic>
{
new {name = "Mexico", count = 19659},
new {name = "Canada", count = 13855},
};
var stringed = t.Select(o => string.Format("{0} {1}", o.name, o.count)).Select(o => Convert.ToString(o)).ToList();
File.WriteAllLines(@"C:\temp\processed.txt", stringed);
}
What is going on here why dynamic ToString(), string.Format() and Convert.ToString() is dynamic? Am I missing something obvious here?
It seems to me like your question can really be boiled down to:
dynamic d = "x";
var v = Convert.ToString(d);
... the compile-time type of v
is dynamic
, as shown by hovering over it in Visual Studio, and you'd expect it to be string
. No need for lists or files.
So, why is this? Basically, C# has a simple rule: almost any operation that uses a dynamic value has a result of dynamic
. That means it doesn't matter if extra overloads are available at execution time that aren't known at compile time, for example.
The only operations I'm aware of where the result of an operation involving a dynamic value isn't dynamic are:
is
operator, e.g. var b = d is Foo; // Type of b is bool
var x = (string) d; // Type of x is string
as
operator, e.g. var y = d as string; // Type of y is string
var z = new Bar(d); // Type of z is Bar
For the simple case of a method call, section 7.6.5 of the C# 5 specification makes it clear that Convert.ToString(d)
will have a type of dynamic
:
An invocation-expression is dynamically bound (ยง7.2.2) if at least one of the following holds:
- The primary-expression has compile-time type dynamic.
- At least one argument of the optional argument-list has compile-time type dynamic and the primary-expression does not have a delegate type.
In this case the compiler classifies the invocation-expression as a value of type
dynamic
.
(As a side-note, the "and the primary-expression does not have the delegate type" part doesn't seem to be resolved anywhere, or honoured by the compiler. If you have a Func<string, string> func = ...; var result = func(d);
the type of result
still appears to be dynamic
rather than string
. I shall look into that...)
See more on this question at Stackoverflow