Reputation: 5151
Inspired by this question I have tried a following code on Mono 2.10.9 and Visual Studio 2010:
public class Example
{
public static void Main()
{
Foo(1);
}
public static void Foo( dynamic x )
{
Example.Bar(x);
}
static void Bar( dynamic x )
{
x++;
}
int count;
void Bar( int x )
{
count++;
}
}
As you can see, Foo
is static, so it can only access static Bar
- and I explicitly invoke the static version!
I know that I would not be able to declare static void Bar( int x )
, because a non-static version exists.
However, changing the argument type of non-static Bar
to, let's say, string, makes everything alright.
Why is that? What are the rules here? Is it possible to call the static method?
Maybe it's a Mono DLR issue?
EDIT: For clarification. I would like to know what rules turn an explicit call to static method (at least I think it's explicit) into a call to a non-static one? This is obviously impossible from static context.
Or, if there are no such rules, can it be a bug? Can this behaviour be somehow avoided?
Upvotes: 3
Views: 432
Reputation: 2445
The key statement there is that "I know that I would not be able to declare static void Bar( int x ), because a non-static version exists.". Using the dynamic keyword defers the overload resolution to run-time, but it doesn't exempt you from that rule when run-time comes along.
When that overload resolution finally occurs, the DLR evaluates all the options available and then chooses the best one. Until this resolution-time, parameters of dynamic type behave much like being of type object (see here). So normally the more specific method that takes an int would be the winner in the overoad resolution and thus be chosen over the one that takes a dynamic/object. This means that the instance method would normally win. The DLR knows that two methods with the same signature cannot vary by staticness. When evaluating the options available, what you are expecting it to do is say "aha! In this case, static void Bar(dynamic x) can be interpreted as static void Bar(int x)". However, if it did say that, then the rule about not having otherwise identical static and non-static methods would be violated. It's internal list of options would contain the static and non-static Bar methods, both of which would have the same signature. So it can't say that. This leaves the only other option, which happens to be an instance method. This is no use in the circumstances so the DLR throws a RuntimeBinderException. If you change the parameter of the instance Bar to something other than an int, then the method signatures do not clash, so the DLR can interpret the static dynamic Bar as taking an int and select that overload instead.
Upvotes: 1
Reputation: 8786
static void Bar( dynamic x )
{
x++;
}
int count;
void Bar( int x )
{
count++;
}
the static function can be seen as (so any call to the static method with a int type parameter will invoke the non-static, better-fit method):
static void Bar( dynamic x )
{
if (x is Int)
Bar(x); //Count++
else
x++;
}
Upvotes: 0