Я возился, пытаясь понять, что я могу и чего не могу делать в отношении дженериков. У меня такая ситуация, и, насколько мне известно, компилятор должен выдавать ошибку в отношении неоднозначных вызовов методов, но компилируется отлично. Это почему?

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;
    }
}
0
Aelphaeis 20 Мар 2014 в 01:02

4 ответа

Лучший ответ

Нет никакой двусмысленности. Как вы сами сказали в комментариях, подпись другая. Внутри контекста ConnectionConnect теперь есть

Strategy(int i)

И

Strategy(params object[] parameters), унаследованный от FunctionStrategyBase

Что вполне приемлемая перегрузка. Независимо от того, что происходит во время выполнения, и странного поведения, которое могло бы произойти, если бы вы не знали о механизме этих функций, компилятор не видит серьезных проблем с этим.

При вызове во время выполнения программа будет использовать самую близкую совпадающую подпись перед проверкой подписей, для которых она может выполнять действительные неявные преобразования. Если вы передадите одно целое в Strategy, будет использован метод Strategy(int i). Если бы у вас его не было, он неявно поместил бы ваш int и передал его в Strategy(params object[] parameters) как функцию языка.

4
selkathguy 19 Мар 2014 в 21:23

В спецификации C # определено, как разрешаются методы, поэтому нет двусмысленности:

7.4.3.2 Улучшенный функциональный член Дан список аргументов A с набором выражений аргументов {E1, E2, ..., EN} и две применимые функции. члены MP и MQ с типами параметров {P1, P2, ..., PN} и {Q1, Q2, ..., QN}, MP определяется как лучший функциональный член, чем MQ, если

...

• В противном случае, если MP применим в его нормальной форме и MQ имеет params и применим только в развернутом виде, тогда MP лучше, чем MQ.

• В противном случае, если MP имеет меньше заявленных параметров, чем MQ, то MP лучше, чем MQ. Это может произойти, если оба метода имеют массивы параметров и применимы только в их развернутых формах.

2
BlueM 19 Мар 2014 в 21:31

Ваш код показывает только один вызов метода, который выполняется с использованием отражения.

Следовательно, разрешение не может быть выполнено во время компиляции, поэтому ваш код компилируется нормально.

Кроме того, здесь нет двусмысленности, потому что каждый класс имеет только один метод.

1
dcastro 19 Мар 2014 в 21:07

Если я правильно интерпретирую этот комментарий

Стратегия, обе стратегии различаются по сигнатуре, как она сможет отличить аргумент param object [] от int i?

Тогда param object[] и int i не нужно различать, потому что param object[] определяет переменное количество параметров любого типа. Таким образом, когда объявляется int i, i помещается в object и передается функции как отдельный массив элементов. Но не уверен, правильно ли я интерпретирую комментарий.

0
LB2 19 Мар 2014 в 21:10