I'm programming in Unity 3.4.2 on OS X using C#.
I have a class like the following:
class Foo<T>
{
public T DoFoo(T bar)
{
float aFloatValue = 1.0f;
// Do other stuff...
return aFloatValue * bar;
}
}
When Unity compiles this class, it gives me this error message:
error CS0019: Operator *' cannot be applied to operands of type
float' and `T'
I know that the types I provide for T will support multiplication with float. How can I implement generic multiplication in this case?
Ahhh, good ol' Haskell.
You can't do that in C#, you should have multiple DoFoo's, one for float, one for double and one for decimal - there aren't all that many float types. You can drop the float variant, too, as it will be implicitly cast into a double anyway.
It's not possible to do this with generics alone as they don't support operators such as +, /, -, *
. To do this you'll need to introduce a layer of abstraction in the form of say an interface or a lambda to provide the operation.
For example
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);
}
}
Now at construction time of Foo<T>
you can tell it how to multiply with a float
type
var f = new Foo<MyType>((x, y) => x * y);
In C# 4, you can use dynamic
if you are confident that float * T => T
.
class Foo<T>
{
public T DoFoo(T bar)
{
dynamic aFloatValue = 1.0f;
// Do other stuff...
return aFloatValue * bar;
}
}
Other options are:
- Use an expression-tree and compile it down to delegate (suitable for caching) that does the multiplication for you.
- Reflection - Either directly, or by producing a delegate first.
- Accept a delegate, as JaredPar mentions.
Since you say dynamic
is not an option: if you obtain MiscUtil, I wrote some support in there for operators on generics. In particular, look at Operator.Multiply
and Operator.MultiplyAlternative
, discussed here. This resolves the methods at runtime, baking them into delegates as needed.
This uses the Expression API, so will work on 3.5, but if needed I could reproduce it for 2.0 using ILGenerator
try this
class Foo<T>
{
public T DoFoo(T bar)
{
float aFloatValue = 1.0f;
var barValue = bar as dynamic;
return aFloatValue * bar;
}
}
it should've work, no errors encountered yet...