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>
,向它添加一堆节点,然后将它传递给那个获取列表的构造函数,并创建另一个新列表它
编译器是否足够智能以确定它不需要两次创建列表?
答案 0 :(得分:5)
这不是一个“足够聪明”的情况 - 编译器按照它所说的去做;你告诉它创建多个列表:它将创建多个列表。
然而,由于你及时发布它们应该收集得相当干净,希望gen-0。因此,除非你在紧密的循环中这样做,否则我不会对此感到太兴奋。
如果你想避免列表,可能会考虑LINQ Concat
,它允许你附加序列而不需要任何额外的列表/集合等。
答案 1 :(得分:2)
不,编译器不能做那样的优化。
当构造函数采用IEnumerable时,您可以创建表达式而不是列表:
public SharpQuery Add(params HtmlNode[] elements) {
return new SharpQuery(_context.Concat(elements), this);
}
Concat
方法将创建一个表达式,该表达式首先返回_context
的项目,然后返回elements
的项目。在构造函数中创建列表时,它将使用直接从_context
和elements
读取的表达式,因此集合仅创建一次。
答案 2 :(得分:2)
如果你告诉它创建一个新对象,它将创建一个新对象。我不认为有一个优化可以用转换和分配替换构造函数调用 - 编译器必须知道构造函数能够以这种方式优化它的方式。
从技术上讲,你可以自己做 - _context = (List<HtmlNode>)nodes;
- 这就是你希望编译器做的事情。或者,更好,_context = nodes as List<HtmlNode> ?? new List<HtmlNode>(nodes)
但无论哪种情况,列表都可能在您的类之外进行修改,因此您必须确保它不会导致意外行为。
到目前为止,它还有一种过早优化的气味。你的代码看起来很好,在看到实际的性能问题之前我不会改变任何东西。
答案 3 :(得分:1)
编译器(JIT)无法对其进行优化。它会为您创建两个列表。但问题是,这是否会给您带来性能问题。通过性能,您可以进行测量,测量和测量。在98%的情况下,我认为这段代码不会给出任何问题。