Как я могу умножить число с плавающей запятой и общий тип? - PullRequest
11 голосов
/ 28 февраля 2012

Я программирую в Unity 3.4.2 на OS X, используя C #.

У меня есть класс, подобный следующему:

class Foo<T>
{
    public T DoFoo(T bar)
    {
        float aFloatValue = 1.0f;
        // Do other stuff...
        return aFloatValue * bar;
    }
}

Когда Unity компилирует этот класс, он дает мнеэто сообщение об ошибке:

ошибка CS0019: оператор *' cannot be applied to operands of type float и `T '

Я знаю, что типы, которые я предоставляю для T, будут поддерживать умножение на float.Как я могу реализовать общее умножение в этом случае?

Ответы [ 5 ]

9 голосов
/ 28 февраля 2012

Ааа, добрый старый Хаскелл.

Вы не можете сделать это в C #, у вас должно быть несколько DoFoo, один для float, один для double и один для десятичной - не так много типов float. Вы также можете отбросить вариант с плавающей точкой, так как он все равно будет неявно приведен к двойному.

7 голосов
/ 28 февраля 2012

Невозможно сделать это только с помощью дженериков, поскольку они не поддерживают такие операторы, как +, /, -, *. Для этого вам нужно ввести слой абстракции в форме, скажем, интерфейса или лямбда-выражения для обеспечения операции.

Например

class Foo<T> {
  Func<T, float, T> _multiplyFunc;
  public Foo(Func<T, float, T> multiplyFunc) {
    _multiplyFunc = multiplyFunc;
  }
  public T DoFoo(T bar) {
    float aFloatValue = 1.0f;
    return _multiplyFunc(bar, aFloatValue);
  }
}

Теперь во время построения Foo<T> вы можете сказать, как умножить на float тип

var f = new Foo<MyType>((x, y) => x * y);
5 голосов
/ 28 февраля 2012

В C # 4 вы можете использовать dynamic, если уверены, что float * T => T.

class Foo<T>
{
    public T DoFoo(T bar)
    {
        dynamic aFloatValue = 1.0f;
        // Do other stuff...
        return aFloatValue * bar;
    }
}

Другие варианты:

  1. Использовать дерево выражений искомпилируйте его, чтобы делегировать (подходит для кэширования), который делает умножение для вас.
  2. Отражение - либо напрямую, либо сначала путем создания делегата.
  3. Примите делегата, как упоминает JaredPar.
3 голосов
/ 28 февраля 2012

Поскольку вы говорите, dynamic не вариант: если вы получаете MiscUtil , я написал некоторую поддержку для операторов обобщений. В частности, посмотрите на Operator.Multiply и Operator.MultiplyAlternative, обсуждаемые здесь . Это разрешает методы во время выполнения, выполняя их по мере необходимости.

Используется Expression API, поэтому он будет работать на 3.5, но при необходимости я мог бы воспроизвести его для 2.0, используя ILGenerator

2 голосов
/ 28 февраля 2012

попробуйте

class Foo<T>
{
    public T DoFoo(T bar)
    {
        float aFloatValue = 1.0f;
        var barValue = bar as dynamic;
        return aFloatValue * bar;
    }
}

все должно работать, ошибок пока не обнаружено ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...