ОБНОВЛЕНИЕ: Начиная с C# 7.3, это больше не должно быть проблемой. Из примечаний к выпуску:
Когда группа методов содержит несколько универсальных методов, аргументы типа которых не удовлетворяют их ограничениям, эти члены удаляются из набора кандидатов.
До C# 7.3:
Итак, я прочитал Эрик Липперт "Ограничения не являются частью подписи", и теперь я понимаю, что спецификация указывает, что ограничения типов проверяются ПОСЛЕ разрешения перегрузки, но я до сих пор не понимаю, почему это ДОЛЖНО быть так. . Ниже приведен пример Эрика:
static void Foo<T>(T t) where T : Reptile { }
static void Foo(Animal animal) { }
static void Main()
{
Foo(new Giraffe());
}
Это не компилируется, потому что разрешение перегрузки для: Foo(new Giraffe())
предполагает, что Foo<Giraffe>
является лучшим соответствием перегрузки, но тогда ограничения типа не работают, и выдается ошибка времени компиляции. По словам Эрика:
Принцип здесь заключается в разрешении перегрузки (и определении типа метода) в поиске наилучшего возможного соответствия между списком аргументов и списком формальных параметров каждого метода-кандидата. То есть они смотрят на сигнатуру метода-кандидата.
Ограничения типа НЕ являются частью подписи, но почему они не могут быть частью? В каких сценариях не рекомендуется рассматривать ограничения типов как часть подписи? Это сложно или невозможно реализовать? Я не выступаю за то, чтобы, если наилучшую выбранную перегрузку по какой-либо причине невозможно вызвать, тогда молча откатывайтесь ко второй лучшей; Я бы ненавидел это. Я просто пытаюсь понять, почему нельзя использовать ограничения типов, чтобы повлиять на выбор лучшей перегрузки.
Я предполагаю, что внутри компилятора C#, только для целей разрешения перегрузки (он не переписывает метод навсегда), следующее:
static void Foo<T>(T t) where T : Reptile { }
превращается в:
static void Foo(Reptile t) { }
Почему вы не можете «втянуть» ограничения типа в список формальных параметров? Как это меняет подпись в плохом смысле? Я чувствую, что это только усиливает подпись. Тогда Foo<Reptile>
никогда не будет рассматриваться как кандидат на перегрузку.
Изменить 2: неудивительно, что мой вопрос был таким запутанным. Я неправильно прочитал блог Эрика и привел неправильный пример. Я отредактировал пример, который считаю более подходящим. Я также изменил название, чтобы оно было более конкретным. Этот вопрос не кажется таким простым, как я сначала себе представлял, возможно, я упускаю какую-то важную концепцию. Я менее уверен, что это материал stackoverflow, возможно, лучше перенести этот вопрос/обсуждение в другое место.