Почему я не могу перегрузить метод одними и теми же параметрами, если я выбрал разные общие ограничения? - PullRequest
3 голосов
/ 19 марта 2011

Если я сделаю это в c # 4.0 .NET

    private static void myMethod<T>(int obj) where T : IDictionary
    {


    }

    private static void myMethod<T>(int obj) where T : ICollection
    {


    }

Я получаю следующую ошибку.

Тип ConsoleApplication1.Program уже определяет член с именем "myMethod" с тем же параметром типы

Я хотел бы знать, почему? Насколько я вижу, оба эти метода можно вызывать без двусмысленности?

Если бы я хотел первый метод, я бы сделал это

myMethod<IDictionary>(50)

и второй метод

myMethod<ICollection>(40)

Какой сценарий я пропускаю? И есть ли способ получить набор перегруженных методов с одинаковыми параметрами, но с другим типом?

Ответы [ 3 ]

9 голосов
/ 19 марта 2011

Разрешение перегрузки в C # вообще не учитывает ограничения.

Из спецификации C #:

7.5.3 Разрешение перегрузки

Разрешение перегрузкиявляется механизмом времени привязки для выбора наилучшего члена функции для вызова с учетом списка аргументов и набора кандидатов в члены функции .

Ссылка на блог @Anthony Pegram - этоГораздо лучше почитать по теме: Ограничения не являются частью подписи

2 голосов
/ 19 марта 2011

Перегрузки основаны только на параметрах функции. Типы возвращаемых данных и параметры шаблона (более конкретно: ограничения) не работают для перегрузки функции. Я не могу сказать вам, почему это так (поскольку я не писал на этом языке и не делал вид, что понимаю все их проблемы). Я могу только сказать вам, что позволит компилятор.

Одной из причин, по которой вам может потребоваться перегрузка ограничений, может быть попытка выполнить эквивалент специализации шаблона C ++. К сожалению, C # не поддерживает это. Шаблоны .Net и шаблоны C ++ - это совершенно разные звери.

Относительно вашего конкретного примера; Есть два способа решить это. И то, и другое требует от вас думать о своей проблеме по-разному.

Реальная проблема заключается в том, что использование, которое вы намереваетесь, вредит вашему дизайну. Перегрузка на самом деле просто синтаксический сахар. Перегрузка помогает людям вызывать ваш общедоступный интерфейс. Это на самом деле не поможет вам внутренне. Фактически, если перегруженные методы выполняют существенно разные вещи, это может усложнить анализ вашего кода во время его отладки и когда вам придется возвращаться и поддерживать его.

Поскольку код, который вызывает эти функции, должен указывать T, вы не экономите на обслуживании, перегружая функцию. Вместо этого вы можете рассмотреть возможность внедрения зависимости (коллекции) в эти методы.

private static void myMethod(int obj, IDictionary dictionary)
{
    // do something with the dictionary here, setting private members while you do it
}

private static void myMethod(int obj, ICollection collection)
{
    // do something with the collection here, setting private members while you do it
}

Если это решение потребует от вас дублировать вызовы new Dictionary или new List слишком часто, или если вы хотите, чтобы метод контролировал создание экземпляра, вы можете просто отказаться от перегрузки.

private static void myMethodWithDictionary<T>(int obj) where T : IDictionary, new()
{
    // Create your new dictionary here, populate it, and set internal members
}

private static void myMethodWithCollection<T>(int obj) where T : ICollection, new()
{
    // Create your new collection here, populate it, and set internal members
}
1 голос
/ 19 марта 2011

Что произойдет, если у вас есть такой класс, что public class Whatever : IDictionary, ICollection?Компилятор не знает, какую перегрузку использовать.

...