29

I was asked this question today:

How can I add an item to a list and return that list back?

The code for List<T>.Add(T) returns void. So you can't do something like this:

var list = new List<string>{"item1","item2"};
var newList = list.Add("item3");

This is related to using AutoMapper, although that part isn't particularly important.

2
  • 2
    Why would you want to create a new list? Why not add to the list and keep referring to the original? Commented Nov 24, 2015 at 15:55
  • The problem, I believe is in Automapper, instead of creating a custom resolver you could do it in one line: ForMember(t=>t.Items,options=>options.MapFrom(s=>new List<string>(t.Items).Add(s.Item)); t.Items is an existing list in an object, possibly with existing data, however, we just want to append the value from the source. Unfortunately, this particular line requires your to return a value so that Automapper can set it to the property. Commented Nov 24, 2015 at 16:06

7 Answers 7

27

One option is Linq, with Concat:

var list = new List<string>{"item1", "item2"};
var newList = list.Concat(new[] { "item3" }).ToList();

In typical Linq fashion, list stays the same, and newList contains all the items from list as well as the items in the new list, in this case just "item3".

You can skip the .ToList() to keep the IEnumerable<string> result if that fits your use case.


If you find yourself doing this often with individual items, you can use something like this extension method to pass them without the new[] { ... } syntax:

public static IEnumerable<T> ConcatItems<T>(this IEnumerable<T> source, params T[] items)
{
    return source.Concat(items);
}

Because of the params array the earlier example becomes:

var list = new List<string>{"item1", "item2"};
var newList = list.ConcatItems("item3").ToList();

Make sure not to mix this up with Union, which removes duplicate items. (Searching for those duplicates is overhead that you probably don't want!)

Sign up to request clarification or add additional context in comments.

2 Comments

I really like this one, I hadn't thought of the Concat function!
I take what i said in my answer back. This is just as readable and more concise. +1
20

The answer to this question was relatively simple:

var list = new List<string>(new List<string>{"item1","item2"}){"item3"};

List<T>() has a constructor that can take in IEnumerable<T> (MSDN). Additionally, you can use the object setter to put new items into the list.

So, for a more complicated example:

var originalList = new List<string>();
originalList.Add("item1");
originalList.Add("item2");

var newList = new List<string>(originalList){"item3"};

4 Comments

I don't completely understand how this answers the first statement in your post (How can I add an item to a list and return that list back?). This creates a new list which seems pointless. Especially since that statement asks for "that list back" which I assume is the one you added to. Or am I misinterpreting that statement?
@DangerZone I will clarify in my question, the statement "that list back" refers to the list of items not necessarily the same reference.
this is the answer with the most concise syntax. using the constructor and the setter during initialization perfectly solves the problem!
@JasonWilczak this is the best way that I know of, but is there a more performant alternative? If the return type is IReadOnlyList<T> then that could allow for array results too.
3

You can simply do :

List<string> list = new List<string>{"item1","item2"};
List<string> newList = null;

(newList = list.ToList()).Add("item3");

Or create your own extension method :

public static class Helper 
{
   public static List<T> MyAdd<T>(this List<T> collection, T item)
   {
      collection.Add(item);
      return collection;
   }
}

And use it :

List<string> list = new List<string>{"item1","item2"};
List<string> newList = list.MyAdd("item3"); // same object though
List<string> newList2 = newList.ToList().MyAdd("item4").MyAdd("item5"); // different object 

Comments

3

Seven years have passed since the question has been asked but Enumerable class now offers Prepend and Append methods that could be used in a straightforward fashion:

var list = new List<string>{"item1","item2"};
var newList = list.Append("item3").ToList();

Comments

2

One property of an ImmutableList<T> (and other similar data structures from System.Collections.Immutable) is that it doesn't mutate the original list, it returns another immutable list with the added value.

So doing this:

var originalImmutable = ImmutableList<int>.Create(1, 2);
var otherImmutable = originalImmutable.Add(3);

Will result in a shallow copied new list each time you call Add.

1 Comment

I think the most important aspect of this answer is that the performance of List<T> and ImmutableList<T> for different operations is very different, and while there are cases where List<T> is faster, this is one where ImmutableList<T> is much, much faster, especially when the first list is large.
2

Using C# 11 (2022), you can write:

[..list, item3]

to get a new List containing the elements of list, and item3 appended to it. It's called list/array "spread expression", kind of similar to Python's spread operator *list.

Before C# 11, .. could only be used in slice expressions, e.g., arr[1..3].

Comments

0

The most readable and maintainable solution is to copy the list and then add the item:

var list = new List<string>{"item1","item2"};
var newList = list.toList();
newList.Add("item3");

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.