Consider the following code:
internal static class Program
{
public static string ExtensionMethod(this string format, dynamic args)
{
return format + args.ToString();
}
private static void Main()
{
string test = "hello ";
dynamic d = new { World = "world" };
// Error CS1973 'string' has no applicable method named 'ExtensionMethod'
// but appears to have an extension method by that name.
// Extension methods cannot be dynamically dispatched.
// Consider casting the dynamic arguments or calling
// the extension method without the extension method syntax.
var result = test.ExtensionMethod(d);
// this syntax works fine
var result2 = Program.ExtensionMethod(test, d);
// for whatever reason, this works, too!
var result3 = test.ExtensionMethod((object)d);
// even this works...
var result4 = test.ExtensionMethod(new { World = "world" });
Console.WriteLine(result);
Console.ReadLine();
}
}
I don't understand the logic behind this. I do understand, that the first argument of an extension method cannot be dynamic. And I even would understand if the dispatch would not work if I passed in something but another dynamic. But obviously it does. It can map other types to dynamic. But that the dispatch does not work when I pass the exact type required by the method? That it cannot map dynamic
to dynamic
? That does not make sense to me.
I can read and understand the error and I obviously know the workarounds, but can anybody enlighten me why this error exists? What would be the deeper problem that I cannot see?
There are several existing questions explaining why first argument (string
) in this case can't be dynamic - How to call an extension method of a dynamic type? showing workaround to convert extension call to regular call. Indeed it works in my case.
There are also plenty of "what is CS1973" questions (https://stackoverflow.com/search?q=CS1973) but again most of them deal with first (this Xxxx
) argument being dynamic
(which is sounds fair to fail) or just show same behavior without explanation why like 'System.Web.Mvc.HtmlHelper' has no applicable method named 'Partial' (calling known extension on strongly typed object but passing dynamic
as second argument).
But that does not explain why when single extension method can be determined at compile time still can't be used which is what this question is about.