Как я могу написать один класс для компиляции несколько раз с разными типами чисел? - PullRequest
5 голосов
/ 01 июля 2011

Я пытаюсь написать классы, которые обрабатывают разные типы чисел. Я знаю, что C # (и, по-моему, .Net в целом) не имеет INumber интерфейса, поэтому я не могу использовать что-то вроде следующего:

    public class Adder<T> where T:INumber
    {
        public T Add(T a, T b)
        {
            return a + b;
        }
    }

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

#if FLOAT 
    public class AdderF
    {
        public float Add(float a, float b)
#else
    public class Adder
    {
        public int Add(int a, int b)
#endif
        {
            return a + b;
        }
    }

Это означает, что мне нужно будет скомпилировать другие Library.dll и LibraryF.dll, однако. Есть ли более элегантное решение для этого?

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

Ответы [ 3 ]

3 голосов
/ 01 июля 2011

Может быть, это может быть полезно: Есть ли общее ограничение C # для типов "действительных чисел"? .

Кажется, что это не возможно напрямую, как вы сказали.Было бы полезно иметь его.

3 голосов
/ 01 июля 2011

Полагаю, это зависит от того, насколько строгим он будет.Вам нужен метод Add, который принимает только два параметра одного и того же типа (int и int, float и float) ...?Если нет, а производительность не является супер-важной, то вы можете просто реализовать свое решение с помощью decimal, и оно все будет работать.

Если оно должно быть строгим, и вам нужны конкретные версии для каждого типа,Вы можете посмотреть на генерацию кода T4.Это похоже на шаблоны C ++ (некоторые люди думают, что шаблоны C ++ и дженерики C # одинаковы, но это не так).

Скотт Хансельман написал интересную статью об этом.

2 голосов
/ 01 июля 2011

Основная проблема здесь заключается в том, что джиттер должен генерировать разные коды операций в зависимости от того, добавляете ли вы плавающие или целые числа, поэтому, хотя код выглядит схожим, на самом деле он совершенно не похож на другие. Это выполнимо в C ++ (потому что шаблоны компилируются отдельно для каждого определения типа), но обобщение .NET работает по-разному. Взгляните на T4 шаблоны как на одно из возможных решений (если вам действительно нужна возможность компилировать как float или int отдельно.)

...