将类型参数转换为基本类型而不进行装箱

时间:2011-01-26 17:29:32

标签: c# generics optimization casting boxing

有没有办法制作像这样的代码:

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和对象的组合呈指数级增长 - 在实际用例中我也想支持双打!没有拳击有没有办法支持这个?也许有不安全的代码?

谢谢! Cauê

2 个答案:

答案 0 :(得分: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

答案 1 :(得分: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);
    }
}

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

至于为什么我要尝试这样做,请阅读上述评论,我仍然会尝试找到最佳方法。

到目前为止,我们有以下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类型,它具有一个调用调用,它将同时获取盒装和未装箱的参数。如果底层函数真的接受未装箱的类型,它将首先尝试使用它们。