namespace System.Collections.Generic
public List<T>
public void AddRange(IEnumerable<T> collection)
It seems like it might be an intentional design decision not to return something. I got bitten by this expecting AddRange to be "fluent."
I was just curious if anyone knew of the design motivations, if there were any, to return nothing?
The AddRange method is called, with the list as its argument. The result is that the current elements of the list are added to the end of the list, duplicating all the elements.
In C#, AddRange adds an entire collection of elements. It can replace tedious foreach-loops that repeatedly call Add on List. Notes, argument. We can pass any IEnumerable collection to AddRange, not just an array or another List.
The AddRange
method was added in .NET 2.0, before LINQ was out, and when "fluency" really wasn't in fashion at all. At the time, no one expected AddRange
to return anything. Plus, in that version of .NET, there was no initializer for List object, so you had to Add() a bunch of items to the list. The AddRange provided a shortcut for not having to loop through and Add objects one by one.
The equivalent LINQ method is IEnumerable<T>.Concat()
The other answers are (essentially) correct, but none of them addresses both possibilities for why AddRange
might return something.
One reason for doing that would be to create a fluent API, like this:
list.Add(1).Add(2).Add(3);
list.AddRange(aGroupOfNumbers).AddRange(theNextGroupOfNumbers);
To achieve this, the list simply returns itself at the end of the method that mutates the list. As Trisped notes, StringBuilder
was doing this before the generic List<T>
was introduced.
Another reason to return something, as Felix K. implies, is that the type is immutable. If a list is immutable, it can't return itself at the end of the method, because it can't mutate itself; and it can't return void, again, because it can't mutate itself. To reflect the change defined by the method contract, the list has to create a new instance that incorporates the change, and then, of course, it has to return that new instance to the caller. People sometimes have a hard time conceiving of that when it comes to collections, but there's a very well-known type that behaves this way: System.String
. As d-b says, nobody expected the list to return anything, because the "classic" imperative programming style uses void methods when mutating data structures.
The designers of the System.Collections.Generic
namespace may not have thought of giving their types a fluent API, but if they did, I could see how they might have decided against it. Certainly, the case for a fluent API in StringBuilder is somewhat stronger than the case for a fluent API in List<T>
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With