代码之家  ›  专栏  ›  技术社区  ›  DxCK

不装箱值类型的变量数?

  •  9
  • DxCK  · 技术社区  · 16 年前
    public void DoSomething(params object[] args)
    {
        // ...
    }
    

    上面签名的问题是,将传递给该方法的每个值类型都将被隐式装箱,这对我来说是一个严重的性能问题。

    有没有一种方法可以在不装箱值类型的情况下清除接受可变数量参数的方法?

    谢谢。

    5 回复  |  直到 16 年前
        1
  •  13
  •   Reed Copsey    16 年前

    public void DoSomething<T>(params T[] args)
    {
    }
    

    但是,这只允许指定单一类型的ValueType。如果您需要混合或匹配值类型,您必须像现在这样允许装箱,或者为不同数量的参数提供特定的重载。


    public void DoSomething<T,U>(T arg1, params U[] args) {}
    public void DoSomething<T,U>(T arg1, T arg2, params U[] args) {}
    

    不幸的是,这需要为您的类型存在多个重载。

    public void DoSomething<T,U>(T[] args1, U[] args2) {}
    

    您失去了良好的编译器语法,但随后可以传递任意数量的两个参数。

        2
  •  3
  •   Randolpho    16 年前

    目前还没有,而且我还没有在发布的.NET4信息中看到任何关于这个问题的内容。

    如果这对您来说是一个巨大的性能问题,您可以考虑几种常见参数列表的重载。

    不过,我想知道:是吗 真正地 性能问题,还是过早优化?

        3
  •  3
  •   Alex Yakunin    16 年前

    假设调用此方法的代码知道参数类型。如果是这样的话,你可以把它们打包成合适的包装 Tuple 类型,并将其实例(元组是引用类型)传递给object这样的方法(因为所有元组都没有公共基)。

    Dictionary<K,V> internal dictionaries

    我写这篇文章是因为实际上我们为类似的问题开发了一个解决方案:我们必须能够用 our own Tuples 无需装箱—主要是比较和反序列化它们(元组由我们开发的数据库引擎使用,因此在我们的示例中,任何基本操作的性能都非常重要)。

    • 我们最终得到了非常复杂的解决方案。看一看,例如 TupleComparer
    • 没有装箱的效果实际上并不像我们预期的那样好:每个装箱/拆箱操作都被单个数组索引和很少的虚拟方法调用所取代,两种方法的成本几乎相同。

    我们开发的方法的唯一好处是不会被垃圾“淹没”Gen0,所以Gen0收集很少发生。由于Gen0收集成本与“活动”对象分配的空间及其计数成正比,因此如果其他分配与我们试图通过这种方式优化的算法的执行混合(或仅仅发生在执行过程中),这将带来明显的优势。

    在这个优化之后,我们的综合测试显示从0%到200-300%的性能提高;另一方面,数据库引擎本身的简单性能测试显示出的改善要少得多(大约5-10%)。在上面的层上浪费了很多时间(还有一个相当复杂的ORM),但是。。。最有可能的是,在实现类似的东西之后,您将真正看到这一点。

    简言之,我建议你把注意力放在别的事情上。如果您完全清楚这是应用程序中的一个主要性能问题,并且没有其他好的解决方法,那么,请继续。。。 .

        4
  •  -1
  •   Community Mohan Dere    9 年前

    public class ClassThatDoes
    {
        public ClassThatDoes DoSomething<T>(T arg) where T : struct
        {
            // process
    
            return this;
        }
    }
    

    现在你叫:

    classThatDoes.DoSomething(1).DoSomething(1m).DoSomething(DateTime.Now)//and so on
    

    但是,这不适用于静态类(扩展方法是可以的,因为您可以返回 this ).

    Can I have a variable number of generic parameters? 以另一种方式问。

    或接受具有 params

    public ClassThatDoes DoSomething<T>(params T[] arg) where T : struct
    {
        // process
    
        return this;
    }
    

    打电话给:

    classThatDoes.DoSomething(1, 2, 3)
                 .DoSomething(1m, 2m, 3m)
                 .DoSomething(DateTime.Now) //etc
    

    创建数组的开销是否小于装箱开销是您必须自己决定的。

        5
  •  -2
  •   Nikos D    16 年前

    可以 使用命名的(因此是可选的)参数!更多信息 this blog post