Как я могу умножить float и общий тип?
Я программирую Unity 3.4.2 на OS X с помощью С#.
У меня есть класс вроде следующего:
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. Как я могу реализовать обобщенное умножение в этом случае?
Ответы
Ответ 1
Ahhh, хороший ol 'Haskell.
Вы не можете сделать это на С#, у вас должно быть несколько DoFoo, одно для float, одно для double и one для десятичного числа - там не так много типов float. Вы также можете оставить вариант с плавающей запятой, так как он будет неявно переброшен в double.
Ответ 2
Это невозможно сделать с помощью генериков, поскольку они не поддерживают такие операторы, как +, /, -, *
. Для этого вам нужно ввести слой абстракции в форме, например, интерфейса или лямбда, чтобы обеспечить операцию.
Например
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);
Ответ 3
В С# 4 вы можете использовать dynamic
, если вы уверены, что float * T => T
.
class Foo<T>
{
public T DoFoo(T bar)
{
dynamic aFloatValue = 1.0f;
// Do other stuff...
return aFloatValue * bar;
}
}
Другие варианты:
- Используйте дерево выражений и скомпилируйте его для делегирования (подходящего для кэширования), который выполняет умножение для вас.
- Отражение - либо непосредственно, либо сначала создавая делегат.
- Принять делегата, как упоминает JaredPar.
Ответ 4
Поскольку вы говорите, что dynamic
не вариант: если вы получаете MiscUtil, я написал некоторую поддержку там для операторов по дженерикам, В частности, посмотрите Operator.Multiply
и Operator.MultiplyAlternative
, обсужденные здесь здесь. Это разрешает методы во время выполнения, при необходимости выкладывая их в делегаты.
В нем используется Expression API, поэтому он будет работать на 3.5, но при необходимости я могу воспроизвести его для 2.0, используя ILGenerator
Ответ 5
попробуйте это
class Foo<T>
{
public T DoFoo(T bar)
{
float aFloatValue = 1.0f;
var barValue = bar as dynamic;
return aFloatValue * bar;
}
}
он должен работать, ошибок еще не встречалось...