Менее универсальные дженерики? Возможное решение для арифметики в универсальных шаблонах C #

В настоящее время дженерики в C # не позволяют выполнять арифметические операции в разумных пределах. Доступны неудобные обходные пути, но ни один из них не является изящным, и все они снижают производительность. Согласно этому интервью, интерфейс с арифметическими типами реализовать невозможно, и поэтому Предлагается один такой обходной путь.

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

Почему я должен указывать на продвинутом языке программирования, как складывать и умножать числа? [Отредактировано по многочисленным просьбам]

Почему бы просто не разрешить Generic быть ограниченным списком типов?

Eg.

class Matrix<T> where T : int,long,float,double

Конечно, синтаксис может быть другим. Но компилятору нужно только проверить, есть ли тип в списке и что используемые операторы работают со всеми типами, что должно быть намного проще, чем очевидно слишком сложное предложение интерфейса.

Есть ли очевидные причины, по которым это невозможно реализовать?


person Mark K    schedule 20.09.2009    source источник
comment
Этот вопрос отвечает на ваш: stackoverflow.com/questions / 32664 /   -  person Locksfree    schedule 20.09.2009
comment
Нет. Он частично отвечает на ряд похожих вопросов, но самый важный из них (рассмотрим последний опубликованный ответ) остается без ответа.   -  person Mark K    schedule 20.09.2009
comment
-1: субъективный / аргументативный. Это невероятно глупо. ... то, что он даже предлагает, это показывает, насколько ограничены разработчики C #.   -  person Charles Bretana    schedule 20.09.2009
comment
Предложение: похоже, что в вашем вопросе слишком много абстракции, возможно, вы могли бы добавить пример того, что вы хотите сделать, и к чему это должно привести.   -  person RBarryYoung    schedule 20.09.2009
comment
Могу ли я предложить вам сформулировать это так, почему это не должно быть реализовано ?. Как говорит Эрик, это может сделать достаточно компетентный разработчик (хотя мне жаль бедного человека, ответственного за работу с десятичными числами, как и все остальное), это, как и большая часть дизайна языков программирования, требует компромиссов. Если бы вы поняли это (и проявили некоторую вежливость), вы бы ответили лучше ...   -  person ShuggyCoUk    schedule 22.09.2009


Ответы (5)


Думаю, вы ищете функциональность языка функционального программирования в ООП. В таком случае используйте FP.

Например, в Scala вы можете заменить операторы, чтобы теперь можно было добавлять или умножать вашу матрицу.

Так обстоит дело с разными языками, но не со всеми языками ООП.

Почему дженерики должны иметь возможность складывать, если неочевидно, как складывать или умножать? Например, если у меня есть класс логарифмов, то умножение - это просто сложение чисел, но как компилятор мог это узнать?

В C # вы можете выполнить перегрузку оператора, которая должна решить проблему, на которую вы жалуетесь: http://msdn.microsoft.com/en-us/library/aa288467%28VS.71%29.aspx

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

person James Black    schedule 20.09.2009
comment
Вы когда-нибудь использовали шаблоны c ++? Они делают это легко. Это не проблема императивной области, это недостаток дизайнерского решения. - person Ed S.; 09.08.2013
comment
@ EdS. Вопрос касался C #, поэтому я так и ответил. Вот сравнение C # и шаблонов, поскольку вы правы, шаблоны более эффективны: msdn.microsoft.com/en-us/library/c6cyy67b.aspx - person James Black; 11.08.2013

Почему бы просто не разрешить Generic быть ограниченным списком типов?

Потому что тогда это не общий. Обобщения расширяют выразительность системы типов в целом; они не предназначены для использования в качестве дешевого механизма поиска и замены в духе шаблонов C ++.

Есть ли очевидные причины, по которым это невозможно реализовать?

Я отрицаю предпосылку вопроса. Его можно реализовать, если бы мы хотели работать вопреки базовым принципам проектирования дженериков. Черт возьми, я мог бы реализовать это менее чем за месяц, я совершенно уверен, учитывая время и бюджет. Однако у меня другие приоритеты.

Это невероятно глупо.

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

Тот факт, что он даже предлагает это, показывает, насколько ограничены разработчики C #.

В самом деле, я хорошо осознаю свои личные ограничения. Мне еще многое предстоит узнать о разработке и реализации языков программирования.

Я также отмечаю, что мы также ограничены нашим бюджетом, рыночными силами, не зависящими от нас, а также многими другими факторами.

И, наконец, позвольте мне воспользоваться этой возможностью, чтобы отметить, что обрушивание личных оскорблений на людей, которые могут ответить на ваш вопрос, работает против вашей цели получить ответ на свой вопрос. Если вам интересна эта тема, вы мог бы прочитать мое короткое эссе на эту тему:

http://blogs.msdn.com/ericlippert/archive/2008/02/20/how-to-not-get-a-question-ansarded.aspx

person Eric Lippert    schedule 20.09.2009
comment
По иронии судьбы, пару дней назад я разговаривал с Андерсом именно на эту тему. Проблема обобщенной арифметики интересна, и совсем не ясно, как лучше всего ее решить и следует ли нам тратить наши ограниченные ресурсы на ее решение вместо чего-то более важного. - person Eric Lippert; 20.09.2009
comment
Эрик: Я думаю, что реальный вопрос тогда в том, почему система типов не лучше включает собственные типы значений, по крайней мере, для дженериков? Это настоящий источник разочарования, ИМХО. Очень трудно понять, как мы можем иметь все эти другие невероятно сложные изощренные типы и наследование в .NET, но такая простая концепция, как (Integer - ›WholeNumbers -› PreciseNumbers - ›Numbers), восходит к основам OO (а также Generics) не могут быть включены? Я устал реализовывать свой собственный Complex / Vector / Matrix / etc, Math для каждого числового типа данных в .NET. - person RBarryYoung; 21.09.2009
comment
Эрик: ... должны ли мы тратить наши ограниченные ресурсы на ее решение вместо чего-то более важного. МЕНЯ: ???!!! Думаю, у нас очень разные взгляды на то, что важно. Превращение нативных типов-значений в первоклассных членов модели наследования и типов .Net кажется мне чертовски важной вещью. - person RBarryYoung; 21.09.2009
comment
@RBarryYoung, если вы пишете такие методы, как следует T One (U a, V b) {return a + b; } но вручную вставьте int, double, byte, long, ulong и т. д. для T, U и V (в некоторых случаях используйте одно и то же). Как только вы разобрались с ошибками и предупреждениями компилятора, посмотрите на декомпилированный код в отражателе. Обратите внимание, как не происходит никаких вызовов функций (текущий «строительный блок» для большинства общего поведения). В самом деле, обратите внимание, что на самом деле в производимом IL почти нет ничего общего. Как бы мне ни нравилась общая арифметика, я согласен с тем, что создание общего механизма сложно. - person ShuggyCoUk; 22.09.2009
comment
F # ведет себя по-другому в этом отношении, за исключением того, что вы заметите, что он приносит с собой другой набор проблем (например, попробуйте присвоить значение int float без явного приведения). - person ShuggyCoUk; 22.09.2009
comment
И все же каждый компилятор BASIC, начиная с 1964 года, был способен правильно компилировать полиморфные арифметические операторы вплоть до машинных инструкций без необходимости зависеть от генерации вызовов функций. Полагаю, сегодняшняя технология компиляторов не так развита, как в 1964 году? Или, может быть, ваше описание - отвлекающий маневр? - person RBarryYoung; 22.09.2009
comment
Типы собственных значений являются первоклассными членами системы типов .NET. Они наследуются от System.ValueType, который наследуется от System.Object. Теперь, возможно, эта иерархия наследования не может успешно моделировать числа так, как вам хотелось бы. К сожалению, сейчас я мало что могу с этим поделать. С другой стороны, к счастью: Microsoft вкладывает все больше и больше средств в понимание потребностей научного и финансового вычислительного сообщества. Надеюсь, что в будущем у нас будет больше инструментов для обслуживания этого сегмента рынка. - person Eric Lippert; 22.09.2009
comment
Хорошо, я знаю, что это старый вопрос, и я вступаю в схватку с парнем, который помогал разрабатывать рассматриваемый язык ... но у меня проблема с первым предложением здесь. Конечно, шаблоны могут быть системой поиска и замены, но они мощные. Я могу банально реализовать Add<T> с помощью шаблонов. В C # это совсем нетривиально. Как системному парню, которому нравится C #, это усложняет мою жизнь. В настоящее время я пишу библиотеку обработки изображений (работодатель не разрешит использование C ++), и * безумно сложно выполнять общие операции с элементами массива, где тип может быть byte, _3 _, ... - person Ed S.; 09.08.2013
comment
... или float. Это слишком сложно. Мне приходится использовать стороннюю универсальную математическую библиотеку (которая работает медленнее, чем собственная математика), и мне также приходится добавлять dynamic здесь и там. Я попытался полностью удалить этот последний бит, но у меня ничего не вышло. Конечный результат - примерно на 6 тыс. Строк кода меньше, но это приводит к потере производительности в 4 раза. Я знаю, что шаблонами можно злоупотреблять, но после долгой работы с обоими языками я должен признать, что предпочитаю их дженерикам C #. Я полагаю, что специальный случай для числовых типов будет стоить того, чтобы такие числовые вычисления, как я. Хорошо, конец напыщенной речи. - person Ed S.; 09.08.2013

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

Кроме того, ограничение, подобное where T: int, не имеет смысла, потому что не может быть никаких типов, производных от int, поскольку int - это структура. Единственный тип, подчиняющийся этому ограничению, - это сам int. Если вы знаете, что ваш тип всегда будет int, дженерики станут спорными.

person Joren    schedule 20.09.2009
comment
Я знаю, что это не шаблоны C ++, и я не хочу, чтобы они были такими. Шаблоны C ++ могут легко вызвать ошибки времени выполнения ... Со списком конкретных типов это невозможно, поскольку все типы могут быть проверены во время компиляции. Что касается второго пункта, ни один здравомыслящий человек действительно не стал бы использовать T: int. Как вы могли заметить, я перечислил четыре типа, а не один. Все дело в том, чтобы уменьшить дублирование кода, поэтому я могу написать одну общую матрицу, а не по одной для каждого типа. - person Mark K; 20.09.2009

Я бы посоветовал (и прошу прощения за свои ограниченные знания, если это кому-то покажется запаздывающим) реализовать как шаблонную, так и общую функциональность с соответствующими ключевыми словами. После прочтения всего сообщения (да, всех) я должен сказать, что согласен с обоими взглядами: дженерики ни в коем случае не должны быть «дешевым механизмом поиска и замены в стиле шаблонов C ++», однако, когда вам нужно реализовать то же самое функция для 2+ типов становится чертовски надоедливой: P

Возможно, интерфейс IArithmetic, в котором указываются операторы, которые необходимо реализовать, можно использовать, чтобы немного ужесточить ограничения?

person Community    schedule 20.09.2009

По той самой причине, которая была четко заявлена ​​в интервью, что добавление такого рода поддержки внесло бы существенные дополнительные сложности с очень незначительным дополнительным преимуществом. Если вы знаете, как разрабатывать и писать компиляторы, вы можете спорить (на каком-нибудь другом форуме), насколько это правда или ложь, но не о том, «глупо ли это» или насколько «ограниченными» могут быть разработчики, использующие этот язык. .

person Charles Bretana    schedule 20.09.2009
comment
Интервью относилось конкретно к конкретной реализации, отличной от той, которую я описываю, и поэтому я назвал его ограниченным. ВСЕГДА есть другой способ что-то сделать ... как вы этого не видите? - person Mark K; 20.09.2009
comment
Я удалил оскорбительный раздел. Я надеюсь, что в будущем вы сможете сосредоточиться на вопросе в целом, а не на каком-то небольшом субъективном разделе. - person Mark K; 20.09.2009
comment
@Mike, вам следует перечитать интервью, в нем, в частности, говорит Андерс, в своем начальном ответе. На самом деле вы спрашиваете, что вы можете сказать с точки зрения ограничений? ... И он говорит: есть целый континуум от ничего до грандиозного сопоставления с образцом. Мы думаем, что ничего не сказать слишком мало, а генеральное сопоставление с образцом становится очень сложным, так что мы находимся посередине. - person Charles Bretana; 22.09.2009
comment
@Mike, этот форум делает определенную и согласованную попытку сосредоточить контент на объективных, технических и существенных темах, поэтому мы, возможно, немного суровы даже в отношении незначительных нарушений. Это главное преимущество работы. Ни один другой форум, который я видел, не оставался таким профессиональным, в котором отсутствовали бы ожесточенные войны и субъективные аргументы. Обратной стороной? Те, у кого тонкая кожа и склонны нарушать эти идеалы, могут немного обидеться. Адаптируйтесь, и вы найдете этот форум ценным дополнением к вашему набору инструментов ... - person Charles Bretana; 22.09.2009