Will the compiler optimize away creating this list twice?
public SharpQuery Add(params HtmlNode[] elements)
{
var 开发者_StackOverflow社区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);
}
I've got a whole bunch of functions that create a new List<T>
, add a bunch of nodes to it, then pass it off to that constructor, which takes the list, and creates yet another new list with it.
Is the compiler smart enough to figure out it doesn't really need to create the list twice?
It isn't a case of being "smart enough" - the compiler does what it is told; you are telling it to create multiple lists: it will create multiple lists.
However, since you release them promptly they should get collected fairly cleanly, hopefully gen-0. So unless you are doing this in a tight loop, I wouldn't get too excited about it.
If you want to avoid the lists, you might consider LINQ Concat
, which allows you to append sequences without any extra lists / collections / etc.
If you tell it to create a new object, it will create a new object. I don't think there is an optimization that would replace a constructor call with a cast and an assigment - the compiler must know way too much about what the constructor does to be able to optimize it this way.
Technically, you could do it yourself - _context = (List<HtmlNode>)nodes;
- that's what you want the compiler to do. Or, better, _context = nodes as List<HtmlNode> ?? new List<HtmlNode>(nodes)
.
But in either case the list might be modified outside of your class, so you must be sure it doesn't cause unexpected behaviour.
So far, it smells of premature optimization. Your code looks fine, and I wouldn't change anything before seeing an actual performance problem here.
No, the compiler can't do optimisations like that.
As the constructor takes an IEnumerable, you can create an expression instead of a list:
public SharpQuery Add(params HtmlNode[] elements) {
return new SharpQuery(_context.Concat(elements), this);
}
The Concat
method will create an expression that first returns the items of _context
, then the items of elements
. When the list is created in the constructor it will use the expression, which reads directly from _context
and elements
, so the collection is only created once.
The compiler (of JIT) can't optimize that. It creates two lists for you. The question however is, is this causing a performance problem for you. With performance, you have measure, measure and measure. In 98% of the cases, I think this code will not give any problems.
精彩评论