Why I cant overload Method with dynamic
and object
Parameters.
void Method(dynamic arg) // Member with same signature is already declared
{
Console.WriteLine("Dynamic");
}
void Method(object arg) // Member with same signature is already declared
{
Console.WriteLine("Not Dynamic");
}
But I can overload Method with dynamic
and another type except object or dynamic it self.
void Method(dynamic arg)
{
Console.WriteLine("Dynamic");
}
void Method(string arg)
{
Console.WriteLine("Not Dynamic");
}
As you can see in the first example compiler can't discriminate two overloads.
I think the second example should not work too because string can be send to both overloads. However Compiler Prefers to call the overload with known type.
I've done some test to see how actually it works.
Method(""); // Prints: Not Dynamic
Method((dynamic)""); // Prints: Not Dynamic
Method(null); // Prints: Not Dynamic
Method(???); // Dynamic for any other type except string and null.
Consider first example works and compiler would decide like this:
Method(new object());// Prints: Not Dynamic
Method((object)5); // Prints: Not Dynamic
Method(???); // Prints: Dynamic for any other type except object and null.
So where is the confusion to the compiler? Why I cant have such overloads?
From the C# 5.0 specification, 4.7 The dynamic type:
The type dynamic has special meaning in C#. Its purpose is to allow dynamic binding, which is described in detail in §7.2.2.
dynamic is considered identical to object except in the following respects:
• Operations on expressions of type dynamic can be dynamically bound (§7.2.2).
• Type inference (§7.5.2) will prefer dynamic over object if both are candidates.
Because of this equivalence, the following holds:
• There is an implicit identity conversion between object and dynamic, and between constructed types that are the same when replacing dynamic with object
• Implicit and explicit conversions to and from object also apply to and from dynamic.
• Method signatures that are the same when replacing dynamic with object are considered the same signature
In fact, once your code is compiled, a method having dynamic
as a parameter is effectively the same as if that same method were declared using object
. It's simply that inside the method, the dynamic
parameter can be used dynamically (i.e. with run-time binding).
Because of this, your first example pair of methods is essentially the same as if you'd declared both methods with the parameter type of object
.
In your second example, just as you can have overloads where one has a parameter of object
and the other a parameter of string
, so too can you pair a method using dynamic
with a method of the same name using string
.
Per the overload resolution rules for C# (also in the specification), as long as the method parameter lists are different in ways that allow one method overload to be chosen as the "best" overload, no compile-time error will occur. In your specific example, passing anything other than a string
to the method automatically excludes the method with string
as a parameter. In the case where you do pass string
, the overload resolution rules select the string
overload as the "best" overload, so no compile error occurs.