Pergunta

I was messing around to see what I could and could not do with regards to generics. I have this situation and as far as I'm concerned the compiler should throw an error with regards to ambiguous method calls but it compiles perfectly fine. Why is that?

public interface IFunctionStrategy<T>
{
    T Strategy(params object[] parameters);
}

public class FunctionStrategyBase<T> : IFunctionStrategy<T>
{
    public virtual T Strategy(params object[] parameters)
    {
        MethodBase current = MethodBase.GetCurrentMethod();
        return (T)GetType().InvokeMember(current.Name, BindingFlags.InvokeMethod | BindingFlags.Public, Type.DefaultBinder, this, parameters);
    }

}

public class ConnectionConnect : FunctionStrategyBase<int>
{
    public int Strategy(int i)
    {
        return i;
    }
}
Foi útil?

Solução

There is no ambiguity. As you said in the comments yourself, the signature is different. Inside of the context of ConnectionConnect, there is now a

Strategy(int i)

and a

Strategy(params object[] parameters) which is inherited from the FunctionStrategyBase

which is perfectly acceptable overloading. Regardless of what happens at runtime and the odd behaviour that could occur if you were unaware of the mechanics of these functions, the compiler sees no strict problems with this.

When calling at runtime, the program will use the closest matching signature, before checking for signatures that it can make valid implicit casts to. If you pass a single int to Strategy, the Strategy(int i) method will be used. If you did not have this, it would then implicitly box your int and pass it to Strategy(params object[] parameters) as a feature of the language.

Outras dicas

Its defined in the C# Spec how the methods are resolved so there is no ambiguity:

7.4.3.2 Better function member Given an argument list A with a set of argument expressions { E1, E2, ..., EN } and two applicable function members MP and MQ with parameter types { P1, P2, ..., PN } and { Q1, Q2, ..., QN }, MP is defined to be a better function member than MQ if

...

• Otherwise, if MP is applicable in its normal form and MQ has a params array and is applicable only in its expanded form, then MP is better than MQ.

• Otherwise, if MP has fewer declared parameters than MQ, then MP is better than MQ. This can occur if both methods have params arrays and are applicable only in their expanded forms.

You code only shows one method call, which is done using reflection.

Therefore, the resolution cannot be done at compile-time, that's why your code compiles just fine.

Also, there's no ambiguity because each class has only one method.

If I interpret this comment correctly

Strategy, both strategies are different in signature, how will it be able to tell between param object[] argument and int i?

then param object[] and int i need not be told apart because param object[] specifies variable number of parameters of any kind. So when int i is declared, i is boxed into an object and passed as single item array to the function. But not sure if I'm interpreting comment correctly.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top