Date: 2010-02-12 07:09 am (UTC)
>Что вы говорите! А я-то думал, что по приведённой вами ссылке указаны НЕКОТОРЫЕ (но не все) отличия темплейтов от дженериков. Видимо, я где-то не заметил фразу "дженерики имеют меньше возможностей, чем C++".
http://msdn.microsoft.com/en-us/library/c6cyy67b(VS.80).aspx
Ну давайте почитаем различия между ними. Первое:
C# generics do not provide the same amount of flexibility as C++ templates.
Дальше идут пять (5) пунктов, начинающихся с C# does not
И еще
At the implementation level, the primary difference is that C# generic type substitutions are performed at runtime
У темплэйтов C++ есть куча недостатков, только они не оказались достаточно значимыми, чтобы быть упомянутыми в статье из MSDN. То, что генерики C# интстанцируются в рантайме -- это круто, но mixed blessing... Это значит, что на очень большом числе архитектур генерики C# работать не будут вообще.

>Может быть, вы мне объясните, с помощью какой магии можно вводить полиморфные типы, если типов нет?
Если типов нет в языке, это не значит, что их нет вообще. Главное, чтобы функция имела общий интерфейс к полиморфному типу, с которым она работает, -- если интерфейса нет, то действительно необходима магия, или хотя бы ЛИСП. Интерфейс может быть любым. Например, qsort из Си может сортировать данные любых типов благодаря указателю на функцию.

В Java генерики не работают с "примитивными" типами. Все остальные типы в Java -- это всегда указатель на объект, в терминах Си -- void * (реже void **). В каждом объекте по фиксированному смещению лежит указатель на дескриптор класса. В дескрипторе класса по фиксированному смещению лежит указатель на таблицу виртуальных функций реализаций (с интерфейсами сложнее, т.к. для них есть множественное наследование). Кстати, конструкторов в этой таблице нет и поэтому нельзя вызвать конструктор для параметризованного типа. Поскольку JIT'ы никогда не хранят скомпилированный код на диске, а только статистики выполнения, проблемы бинарной несовместимости не возникает. Таким образом, генерик-функция работает фактически с одним типом -- void * с пришпиленными таблицами , по которым процессор может найти нужные ООП функции. Это в первом приближении, а во втором JIT-компилятор может создать сколько угодно экземпляров генерик-функции с заинлайненными вызовами и это поведение контролировать на уровне исходного кода нельзя. Следствие -- что генерики в Java бесполезны без ООП. Другое следствие -- если бы не было общего предка (Object), то ситуация была гораздо хуже. В C# "примитивные" типы при подстановке в генерик подвергаются автобоксингу -- и дальше действует схема, похожая на вышеописанную, но с существенными отличиями. Инстанцирование в C# необходимо, т.к. там могут быть значимые типы (которые не являются void*) и таким образом, функция действительно должна работать с другими объектами.

>В любом случае, это неправда - пример приведён.
Имеющий практического смысла меньше, чем ray-tracer в compile-time.
>Вы спросили про продакшен. Мне лично представляется, что продакшен-код в подавляющем большинстве случаев содержит ОЧЕНЬ много строк.
Особенно если это индусский или китайский код.

Как надо: запускаем Maple или если ее нет, идем на http://www.wolframalpha.com/input/
вбиваем sum(i=0..n-1,(2*i+1)*i*i)
После чего пишем в код обширный комментарий, проверку и строку, которая вычисляет нужное за O(1)
if(n<0) throw чего-то там;
return (n-1)*n*(3*n*n-n-1)/6;
если не будет хватать диапазона значений, легко будет изменить одну строку, а не раскиданные по всему коду.
If you don't have an account you can create one now.
HTML doesn't work in the subject.
More info about formatting