Yes, you have to loop, unfortunately. This is an O(n) operation - O(1) for each entry added. There's no risk of requiring a buffer to be resized and copied, etc - although of course garbage collection might do roughly that :) You could even write handy extension methods:
public static class LinkedListExtensions
{
public static void AppendRange<T>(this LinkedList<T> source,
IEnumerable<T> items)
{
foreach (T item in items)
{
source.AddLast(item);
}
}
public static void PrependRange<T>(this LinkedList<T> source,
IEnumerable<T> items)
{
LinkedListNode<T> first = source.First;
// If the list is empty, we can just append everything.
if (first is null)
{
AppendRange(source, items);
return;
}
// Otherwise, add each item in turn just before the original first item
foreach (T item in items)
{
source.AddBefore(first, item);
}
}
}
EDIT: Erich's comment suggests why you might think this is inefficient - why not just join the two lists together by updating the "next" pointer of the tail of the first list and the "prev" pointer of the head of the second? Well, think about what would happen to the second list... it would have changed as well.
Not only that, but what would happen to the ownership of those nodes? Each is essentially part of two lists now... but the LinkedListNode<T>.List
property can only talk about one of them.
While I can see why you might want to do this in some cases, the way that the .NET LinkedList<T>
type has been built basically prohibits it. I think this doc comment explains it best:
The LinkedList<T>)
class does
not support chaining, splitting,
cycles, or other features that can
leave the list in an inconsistent
state.