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

编译器会优化创建这个列表两次吗?

  •  4
  • mpen  · 技术社区  · 14 年前
    public SharpQuery Add(params HtmlNode[] elements)
    {
        var nodes = new List<HtmlNode>(_context.Count + elements.Length);
        nodes.AddRange(_context);
        nodes.AddRange(elements);
        return new SharpQuery(nodes, this);
    }
    
    public SharpQuery(IEnumerable<HtmlNode> nodes, SharpQuery previous = null)
    {
        if (nodes == null) throw new ArgumentNullException("nodes");
        _previous = previous;
        _context = new List<HtmlNode>(nodes);
    }
    

    我有一大堆的函数来创建一个新的 List<T> ,向其中添加一组节点,然后将其传递给该构造函数,该构造函数获取该列表,并使用该列表创建另一个新列表。

    编译器是否足够聪明,能够发现它实际上不需要创建两次列表?

    4 回复  |  直到 14 年前
        1
  •  5
  •   Marc Gravell    14 年前

    这并不是一个“足够聪明”的例子——编译器会按照命令做;你告诉它创建多个列表:它会创建多个列表。

    应该 收集得相当干净,希望是0代。所以除非你是在一个紧密的循环中做这件事,否则我不会太兴奋。

    如果你想避开名单,你 考虑LINQ Concat ,它允许您附加序列,而不需要任何额外的列表/集合等。

        2
  •  2
  •   VladV    14 年前

    如果告诉它创建一个新对象,它将创建一个新对象。我不认为有一个优化可以用一个强制类型转换和一个assignment替换构造函数调用——编译器必须非常了解构造函数的功能,这样才能优化它。

    严格来说,你可以自己做- _context = (List<HtmlNode>)nodes; -这就是你想要编译器做的。或者,更好, _context = nodes as List<HtmlNode> ?? new List<HtmlNode>(nodes) .

    到目前为止,它还带有过早优化的味道。您的代码看起来很好,在看到实际的性能问题之前,我不会更改任何内容。

        3
  •  2
  •   Guffa    14 年前

    不,编译器不能这样做优化。

    由于构造函数采用IEnumerable,因此可以创建表达式而不是列表:

    public SharpQuery Add(params HtmlNode[] elements) {
      return new SharpQuery(_context.Concat(elements), this);
    }
    

    Concat 方法将创建一个表达式,该表达式首先返回 _context elements . 当在构造函数中创建列表时,它将使用表达式,该表达式直接从 _上下文 ,因此集合只创建一次。

        4
  •  1
  •   Steven    14 年前