The following code demonstrates my question:
public class DynamicExample
{
public void DoSomething()
{
var x = new ExpandoObject();
dynamic d = x;
d.GetString = (Func<string>)(() => "Some Value");
d.GetString().SomeStringExtension(); // Doesn't work - expected
((string)d.GetString()).SomeStringExtension(); // Works - expected
Build(d).SomeStringExtension(); // Doesn't work - unexpected?
}
private static string Build(dynamic d)
{
return (string)d.GetString();
}
}
public static class StringExtensions
{
public static int SomeStringExtension(this string s)
{
return s.Length;
}
}
The question is, why is there a difference for the compiler between casting the type inline to the extension method call and moving that cast out into a separate method?
Build(d)is still a dynamic expression – the compile-time type of the method isdynamiceven though you can see exactly what’s going on. That means extension methods won’t work.Basically the compiler follows reasonably simple rules to determine what the type of an expression is, and almost any expression involving
dynamicends up being considered as a dynamic expression. The exceptions to this are:d is SomeType(always considered to bebool)asThat’s it as far as I can remember, although I could be mistaken…
Now the language could have been designed such that this case would statically resolve the call to
Buildas the only sensible one – after all, it’s impossible fordto be of any type which would change which method is called – but to specify the exact rules for that would make the language specification (and the compiler) significantly more complicated for relatively little gain.