Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何避免值类型的装箱_C#_Generics_Boxing - Fatal编程技术网

C# 如何避免值类型的装箱

C# 如何避免值类型的装箱,c#,generics,boxing,C#,Generics,Boxing,假设我有一个类根据传递给它的泛型类型调用一个Func,我有一个该类所需的公共接口,如下所示: var r = new Resolver(); var i = r.Invoke(10); // invokes some function `Func<int,int>` var j = r.Invoke("Hello"); // Same, but `Func<string,string>` var k = r.Invoke(10, 10); // Same but 'Fu

假设我有一个类根据传递给它的泛型类型调用一个
Func
,我有一个该类所需的公共接口,如下所示:

var r = new Resolver(); 
var i = r.Invoke(10); // invokes some function `Func<int,int>`
var j = r.Invoke("Hello"); // Same, but `Func<string,string>`
var k = r.Invoke(10, 10); // Same but 'Func<int,int,int>`
class Resolver {
    readonly IDictionary<Type, Func<object, object>> _funcs = new Dictionary<Type, Func<object, object>>();

    public Resolver() {
        _funcs.Add(typeof(int), o => (int)o*(int)o);
        _funcs.Add(typeof(string), o => (string)o + (string)o);
        // and so on; 
    }

    public T Invoke<T>(T t1) {
        return (T) _funcs[typeof (T)](t1);
    }

    public T Invoke<T>(T t1, T t2) {
        return (T)_funcs[typeof(T)](t1);
    }
}
var r=new Resolver();
变量i=r.Invoke(10);//调用一些函数'Func'`
var j=r.Invoke(“Hello”);//相同,但是'Func'`
var k=r.Invoke(10,10);//相同但“Func”`
我有这样一个实现:

var r = new Resolver(); 
var i = r.Invoke(10); // invokes some function `Func<int,int>`
var j = r.Invoke("Hello"); // Same, but `Func<string,string>`
var k = r.Invoke(10, 10); // Same but 'Func<int,int,int>`
class Resolver {
    readonly IDictionary<Type, Func<object, object>> _funcs = new Dictionary<Type, Func<object, object>>();

    public Resolver() {
        _funcs.Add(typeof(int), o => (int)o*(int)o);
        _funcs.Add(typeof(string), o => (string)o + (string)o);
        // and so on; 
    }

    public T Invoke<T>(T t1) {
        return (T) _funcs[typeof (T)](t1);
    }

    public T Invoke<T>(T t1, T t2) {
        return (T)_funcs[typeof(T)](t1);
    }
}
类解析器{
只读IDictionary _funcs=新字典();
公共解析器(){
_函数Add(typeof(int),o=>(int)o*(int)o);
_funcs.Add(typeof(string),o=>(string)o+(string)o);
//等等;
}
公共T调用(T t1){
返回(T)_funcs[typeof(T)](t1);
}
公共T调用(t1,t2){
返回(T)_funcs[typeof(T)](t1);
}
}
但是对于值类型来说,性能是可怕的,因为
Func
的内部实现将
object
作为泛型类型而导致了装箱


有没有一种方法可以实现我想要的公共接口,从而避免值类型的装箱?我也不介意实现内部的静态类型安全性,但是可以不使用

您可以执行以下简单的技巧(不比当前实现的类型安全性高或低):


您可以使用静态泛型变量来缓存解析器。在我的快速测试中,这花费了大约三分之一的时间来执行并避免了装箱

由于
ResolverCache.Resolver
是与
ResolverCache.Resolver
不同的变量,因此可以以类型安全的方式存储不同的解析器

class Resolver
{
    static class ResolverCache<T>
    {
        public static T Resolver { get; set; }
    }

    void AddResolver<T>(T resolver)
    {
        ResolverCache<T>.Resolver = resolver;
    }

    public Resolver()
    {
        Func<int, int> intResolver = o => (int)o * (int)o;
        Func<int, int, int> intResolver2 = (o, p) => (int)o * (int)p;
        Func<string, string> stringResolver = o => (string)o + (string)o;

        AddResolver(intResolver);
        AddResolver(intResolver2);
        AddResolver(stringResolver);

        // and so on; 
    }

    public T Invoke<T>(T t1)
    {
        var resolver = ResolverCache<Func<T, T>>.Resolver ?? (v => { throw new Exception("No resolver registered."); });
        return resolver(t1);
    }

    public T Invoke<T>(T t1, T t2)
    {
        var resolver = ResolverCache<Func<T, T, T>>.Resolver ?? ((v, u) => { throw new Exception("No resolver registered."); });
        return resolver(t1, t2);
    }
}
类解析器
{
静态类解析缓存
{
公共静态T解析器{get;set;}
}
void AddResolver(T解析器)
{
ResolverCache.Resolver=解析器;
}
公共解析器()
{
Func intResolver=o=>(int)o*(int)o;
Func intResolver2=(o,p)=>(int)o*(int)p;
Func stringResolver=o=>(字符串)o+(字符串)o;
AddResolver(intResolver);
AddResolver(intResolver2);
AddResolver(stringResolver);
//等等;
}
公共T调用(T t1)
{
var resolver=ResolverCache.resolver??(v=>{抛出新异常(“未注册解析程序”);});
返回解析器(t1);
}
公共T调用(t1,t2)
{
var resolver=ResolverCache.resolver??((v,u)=>{抛出新异常(“未注册任何解析程序”);});
返回解析器(t1,t2);
}
}

这是避免我假设的问题的好方法。然而,根据我自己的测试,很明显拳击不是我遇到的性能问题的主要原因。尽管如此,我还是感谢你的答复。谢谢大家!+1完美。我一直在寻找一种通过泛型而不引发装箱的方法,这正是我解决这个问题所需要的推动力。非常感谢。