How can I multiply a float and a generic type?

2019-03-25 11:38发布

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?

标签: c# generics mono
5条回答
一夜七次
2楼-- · 2019-03-25 12:14

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.

查看更多
够拽才男人
3楼-- · 2019-03-25 12:19

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);
查看更多
smile是对你的礼貌
4楼-- · 2019-03-25 12:19

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:

  1. Use an expression-tree and compile it down to delegate (suitable for caching) that does the multiplication for you.
  2. Reflection - Either directly, or by producing a delegate first.
  3. Accept a delegate, as JaredPar mentions.
查看更多
对你真心纯属浪费
5楼-- · 2019-03-25 12:20

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...

查看更多
老娘就宠你
6楼-- · 2019-03-25 12:28

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

查看更多
登录 后发表回答