Позвольте мне начать смело: Я прекрасно понимаю мотивацию его наличия и не могу понять мотивацию некоторых людей чтобы возразить против этого ...
Что вы хотите, это невиртуальный ad hoc полиморфизм.
- Специальные: реализация может варьироваться
- невиртуальный: по соображениям производительности; compiletime dispatch
Остальное - это сахар, на мой взгляд.
C++ уже имеет специальный полиморфизм через шаблоны. «Концепции», однако, прояснили бы, какие специальные полиморфные функциональные возможности используются, с помощью определяемого пользователем объекта.
C# просто не имеет никакого способа это сделать.Подход, который не был бы неинтересным: Если бы такие типы, как float, просто реализовали бы что-то вроде «INumeric» или «IAddable» (...), мы бы, по крайней мере, могли написать общий min, max, lerp и на основе этого зажима, maprange, bezier (...). Однако это было бы не быстро. Ты этого не хочешь.
Способы фиксации этого: Поскольку .NET делает JIT компиляции в любом случае также генерирует разный код для List<int>
, чем для List<MyClass>
(из-за разности значений и ссылочных типов), вероятно, не хотел бы добавить, что большая часть накладных расходов для также генерируют разный код для специальных полиморфных частей. Язык C# просто нужен способ выразить это. Один из способов - это то, что вы набросали.
Другим способом было бы добавить ограничения типа функции с помощью специальной полиморфный функции:
U SuperSquare<T, U>(T a) applying{
nonvirtual operator (*) T (T, T)
nonvirtual Foo U (T)
}
{
return Foo(a * a);
}
Конечно, вы могли бы в конечном итоге все больше и больше ограничений при реализации Bar, который использует Foo. Таким образом, вам может понадобиться механизм, чтобы дать имя нескольким ограничениям, которые вы регулярно используете ... Однако это опять-таки сахара, и один из способов приблизиться к нему - это просто использовать концепцию класса ...
Предоставление имени несколько ограничений, как определение класса типа, но я хотел бы просто смотреть на нее как своего рода механизм аббревиатурой - сахар для произвольного набора ограничений типа функции:
// adhoc is like an interface: it is about collecting signatures
// but it is not a type: it dissolves during compilation
adhoc AMyNeeds<T, U>
{
nonvirtual operator (*) T (T, T)
nonvirtual Foo U (T)
}
U SuperSquare<T, U>(T a) applying AMyNeeds<T, U>
{
return Foo(a * a);
}
на каком-то месте «основной» все аргументы типа известны, и все становится конкретным и может быть скомпилировано вместе.
Отсутствует все еще отсутствие создания различных реализаций. В верхнем примере мы только использовали полиморфные функции, и пусть все знают ...
Осуществление затем снова может следовать по пути методов расширения - в их способности добавлять функциональные возможности любого класса в любой момент:
public static class SomeAdhocImplementations
{
public nonvirtual int Foo(float x)
{
return round(x);
}
}
В главном теперь вы можете написать:
int a = SuperSquare(3.0f); // 3.0 * 3.0 = 9.0 rounded should return 9
компилятор проверяет все «невиртуальные» специальные функции, находит как встроенный оператор float (*), так и int Foo (float)
и, следовательно, способен скомпилировать эту строку.
Конечно, полиморфизм ad hoc, конечно же, имеет недостаток, который необходимо перекомпилировать для каждого типа времени компиляции, чтобы вставить правильные реализации. И, вероятно, IL не поддерживает то, что помещается в dll. Но, возможно, они все равно работают над этим ...
Я не вижу реальной необходимости в создании конструкции типа класса. Если что-то не получилось при компиляции, мы получим ошибки ограничений или если они были связаны вместе с «adhoc» кодеком, сообщение об ошибке могло бы получить еще более читаемый.
MyColor a = SuperSquare(3.0f);
// error: There are no ad hoc implementations of AMyNeeds<float, MyColor>
// in particular there is no implementation for MyColor Foo(float)
Но, конечно же, можно предположить, что инициализация класса типа/«интерфейса адгорного полиморфизма». В сообщении об ошибке будет указано: «The AMyNeeds constraint of SuperSquare has not been matched. AMyNeeds is available as StandardNeeds : AMyNeeds<float, int> as defined in MyStandardLib
». Также можно было бы поместить реализацию в класс вместе с другими методами и добавить «adhoc interface» в список поддерживаемых интерфейсов.
Но независимо от конкретного дизайна языка: я не вижу недостатков добавления их так или иначе. Сохранение статически типизированных языков всегда необходимо подтолкнуть границу выразительной мощности, так как они начались с разрешения слишком мало, что, как правило, является меньшим набором выразительной мощности, который ожидал нормальный программист ...
tldr : Я на вашей стороне. Подобные вещи отстойны в основных статически типизированных языках. Хаскелл показал путь.
.Net поддерживает один тип класс: новый. Я предполагаю, что они не реализованы, потому что то, что .Net уже «достаточно хорошо», по сравнению со стоимостью реализации. –
Я не думаю, что я запутываю эти вещи, я сравниваю их и объясняю, почему на C++ неявно реализованные «концепции» пока еще предпочитают явно определенные «концепции», несмотря на то, что типы (и должен быть) явно определен в C++. По крайней мере, я пытаюсь - я соглашаюсь, что я, возможно, потерпел неудачу ... –
@Steve Jessop: Мой комментарий не относится к вашему сообщению в частности (это действительно очень полезный ответ) - я просто хотел предотвратить возможность непонимания вопроса в целом. – Dario