2

有没有办法让这样的代码工作:

public class Func2<A, B>
{
    private Func<A, B> f;

    public Func2(Func<A, B> f)
    {
        this.f = f;
    }

    public object invoke(object obj, long l)
    {
        if (typeof(B) == typeof(long))
        {
            if (obj != null)
                l = (long)obj;
            return f((B)l); //error! cannot convert type 'long' to 'B'
        } else {
            return f((B)obj);
        }
    }
}

这里的问题是我不能直接将 B 转换为 long 而不先将 B 转换为对象。我试图不惜一切代价避免装箱,因为它会减慢功能上的很多快速操作。那么有什么方法可以实现这一点吗?

我知道我实际上可以定义一个专门的 Func2 来专门处理 B 为 long 的情况。但随着函数数量的增长,long 和对象的组合呈指数增长——在实际用例中,我还希望支持双精度数!有没有什么方法可以在没有拳击的情况下支持这一点?也许有不安全的代码?

谢谢!考埃

4

2 回答 2

3

您可以重载该方法,而不是将long值转换为A,您可以将委托转换为Func<long, B>

public class Func2<A, B> {

  private Func<A, B> f;

  public Func2(Func<A, B> f) {
    this.f = f;
  }

  public B invoke(long a) {
    if (typeof(A) == typeof(long)) {
      return (f as Func<long, B>)(a);
    } else {
      throw new NotSupportedException();
    }
  }

  public B invoke(object a) {
    return f((A)a);
  }

}

例子:

Func2<long, string> f = new Func2<long, string>(l => l.ToString());

Console.WriteLine(f.invoke(42)); // calls the invoke(long) method
Console.WriteLine(f.invoke("x")); // calls the invoke(object) method
于 2011-01-26T17:51:23.023 回答
0

刚刚找到答案!:)

public object invoke(object obj, long l)
{
    if (typeof(B) == typeof(long))
    {
        if (obj != null)
            l = (long)obj;
        Func<A, long> x = (Func<A, long>)(object)f;
        return x(l);
    } else {
        return f((B)obj);
    }
}

这样我们就不必将 long 自动装箱到对象,但我们实际上将 Func 类型转换为接收我们指定的 long!

至于我为什么要这样做,请阅读上面的评论,我仍然会努力寻找最好的方法来做到这一点。

到目前为止,我们有以下 Haxe 代码:

var f:Int->Int->Float = function(x:Int, y:Int) return x + y + 0.5;
var f2:Dynamic->Dynamic->Dynamic = f; // ok
var f3:Dynamic->Int->Dynamic = f; //also ok
f2(10, 30); // ok - this will box the 10 and 30

我想要做的是创建一个 Fun3 类型,它有一个调用调用,它将接受装箱和未装箱的参数。如果底层函数真的接受未装箱的类型,它将首先尝试使用它们。

于 2011-01-26T17:49:24.647 回答