Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the Generic List AddRange return void instead of a list?

Tags:

c#

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?

like image 602
Joshua Enfield Avatar asked Sep 14 '12 21:09

Joshua Enfield


People also ask

What does list AddRange do?

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.

How does AddRange work in c#?

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.


2 Answers

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()

like image 103
edeboursetty Avatar answered Oct 07 '22 19:10

edeboursetty


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>.

like image 35
phoog Avatar answered Oct 07 '22 20:10

phoog