176

In C#, is there an inline shortcut to instantiate a List<T> with only one item?

I'm currently doing:

new List<string>( new string[] { "title" } ))

Having this code everywhere reduces readability. I've thought of using a utility method like this:

public static List<T> SingleItemList<T>( T value )
{
    return (new List<T>( new T[] { value } ));
}

So I could do:

SingleItemList("title");

Is there a shorter / cleaner way?

Alexander Farber
  • 21,519
  • 75
  • 241
  • 416
Ryan Ische
  • 3,536
  • 3
  • 21
  • 20

17 Answers17

311

Simply use this:

List<string> list = new List<string>() { "single value" };

You can even omit the () braces:

List<string> list = new List<string> { "single value" };

Update: of course this also works for more than one entry:

List<string> list = new List<string> { "value1", "value2", ... };
M4N
  • 94,805
  • 45
  • 217
  • 260
55
var list = new List<string>(1) { "hello" };

Very similar to what others have posted, except that it makes sure to only allocate space for the single item initially.

Of course, if you know you'll be adding a bunch of stuff later it may not be a good idea, but still worth mentioning once.

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
  • Capacity set to one. I voted for four answers on this page including both of Jon Skeet's but I consider this one to be the most correct. – The Lonely Coder Dec 09 '14 at 14:51
40

Michael's idea of using extension methods leads to something even simpler:

public static List<T> InList<T>(this T item)
{
    return new List<T> { item };
}

So you could do this:

List<string> foo = "Hello".InList();

I'm not sure whether I like it or not, mind you...

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    I'm also not sure I like it: isn't this a "strange" extension of the string type (for example) ? – M4N Jan 20 '09 at 19:56
  • 1
    I haven't made it to extension methods in your book yet, Jon :-) This does seems sort of strange, but I like the utility of it. Thanks Martin and Jon. – Ryan Ische Jan 20 '09 at 20:08
  • 3
    @Martin: It's a strange extension of *every* type. This is generally discouraged, but it's an interesting general idea. – Jon Skeet Jan 20 '09 at 20:10
  • 5
    It hase some internal domain specific language uses, especially with value types. Take for example: clock.AlertUser.In(1.Minute) reads much better than clock.AlertUser(TimeSpan.FromMinutes(1)); – Michael Meadows Jan 20 '09 at 20:19
18

A different answer to my earlier one, based on exposure to the Google Java Collections:

public static class Lists
{
    public static List<T> Of<T>(T item)
    {
        return new List<T> { item };
    }
}

Then:

List<string> x = Lists.Of("Hello");

I advise checking out the GJC - it's got lots of interesting stuff in. (Personally I'd ignore the "alpha" tag - it's only the open source version which is "alpha" and it's based on a very stable and heavily used internal API.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
17
new[] { "item" }.ToList();

It's shorter than

new List<string> { "item" };

and you don't have to specify the type.

Waldemar Gałęzinowski
  • 1,125
  • 1
  • 10
  • 18
9

Use an extension method with method chaining.

public static List<T> WithItems(this List<T> list, params T[] items)
{
    list.AddRange(items);
    return list;
}

This would let you do this:

List<string> strings = new List<string>().WithItems("Yes");

or

List<string> strings = new List<string>().WithItems("Yes", "No", "Maybe So");

Update

You can now use list initializers:

var strings = new List<string> { "This", "That", "The Other" };

See http://msdn.microsoft.com/en-us/library/bb384062(v=vs.90).aspx

Michael Meadows
  • 27,796
  • 4
  • 47
  • 63
  • Maybe this is due to newer versions of C# since 2009, but I find `new List {"Yes"}` to be better... ? – ErikE Jul 18 '14 at 00:02
  • @ErikE According to Microsoft documentation (http://msdn.microsoft.com/en-us/library/bb384062(v=vs.90).aspx) this was supported in Visual Studio 2008. I can't remember that far back to say definitively if I over-complicated this at the time. Updating. – Michael Meadows Dec 11 '14 at 18:30
8

Yet another way, found on "C#/.Net Little wonders" (unfortunately, the site doesn't exist anymore):

Enumerable.Repeat("value",1).ToList()
Grzegorz Sławecki
  • 1,727
  • 14
  • 27
6

For a single item enumerable in java it would be Collections.singleton("string");

In c# this is going to be more efficient than a new List:

public class SingleEnumerator<T> : IEnumerable<T>
{
    private readonly T m_Value;

    public SingleEnumerator(T value)
    {
        m_Value = value;
    }

    public IEnumerator<T> GetEnumerator()
    {
        yield return m_Value;
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        yield return m_Value;
    }
}

but is there a simpler way using the framework?

Squirrel
  • 1,355
  • 2
  • 16
  • 25
  • That's actually the best answer in my opinion. It is a very common pattern to have a single item list, to reduce allocation size. If you are already looking for a shortcut you might as well combine the convenient with the good. – Alexander Oh Mar 09 '20 at 10:12
  • Wouldn't there be a gain in using a `readonly struct` here? Also, making it a `IReadOnlyCollection` or `IReadOnlyList` is cheap and may be useful (Linq do optimizations in such cases). – Orace Oct 21 '22 at 11:36
4

I've got this little function:

public static class CoreUtil
{    
    public static IEnumerable<T> ToEnumerable<T>(params T[] items)
    {
        return items;
    }
}

Since it doesn't prescribe a concrete return type this is so generic that I use it all over the place. Your code would look like

CoreUtil.ToEnumerable("title").ToList();

But of course it also allows

CoreUtil.ToEnumerable("title1", "title2", "title3").ToArray();

I often use it in when I have to append/prepend one item to the output of a LINQ statement. For instance to add a blank item to a selection list:

CoreUtil.ToEnumerable("").Concat(context.TrialTypes.Select(t => t.Name))

Saves a few ToList() and Add statements.

(Late answer, but I stumbled upon this oldie and thought this could be helpful)

Gert Arnold
  • 105,341
  • 31
  • 202
  • 291
3

Try var

var s = new List<string> { "a", "bk", "ca", "d" };
Maher Abuthraa
  • 17,493
  • 11
  • 81
  • 103
delwasaf ewrew
  • 557
  • 1
  • 8
  • 21
3

The declarations make it so easy now to do in C# 10.0 that I don't think theres a need for any helper. Just add the new(){} around any value you want to cast to a list.

List<string> values = new() { "single value" };
clamchoda
  • 4,411
  • 2
  • 36
  • 74
2

Inspired by the other answers (and so I can pick it up whenever I need it!), but with naming/style aligned with F# (which has a standard singleton function per data structure*):

namespace System.Collections.Generic
{
    public static class List
    {
        public static List<T> Singleton<T>(T value) => new List<T>(1) { value };
    }
}

* except for ResizeArray itself of course, hence this question :)


In practice I actually name it Create to align with other helpers I define such as Tuple.Create, Lazy.Create[2], LazyTask.Create etc:

namespace System.Collections.Generic
{
    public static class List
    {
        public static List<T> Create<T>(T value) => new List<T>(1) { value };
    }
}

[2]

namespace System
{
    public static class Lazy
    {
        public static Lazy<T> Create<T>(Func<T> factory) => new Lazy<T>(factory);
    }
}
Ruben Bartelink
  • 59,778
  • 26
  • 187
  • 249
  • Thanks! My solution as well. Couple things: (1) your list implementation is not public, so it can't be used outside the declaring assembly, and (2) what is the purpose of stuffing these into the System namespace? – Codure Apr 04 '17 at 15:43
  • @StephenRobinson reason for putting the `Lazy` extension in `System` is that `Lazy` itself is in `System` [and hence `Create` would appear in the compleiton lists without a `using`]. There's nothing to be gained from forcing people to `open` a diff namespace? Making the other thing private was not intentional; fixed – Ruben Bartelink Apr 06 '17 at 13:12
2

You can also do

new List<string>() { "string here" };
Rune Grimstad
  • 35,612
  • 10
  • 61
  • 76
2

I would just do

var list = new List<string> { "hello" };
Brian Rasmussen
  • 114,645
  • 34
  • 221
  • 317
2

Just to elaborate a little bit more:
As of C# 9.0, we have 'Target-typed new' such that when the target type is known, you can omit the type name.

@clamchoda shows how to use target-typed new when declaring a variable.
If you assign a previously declared variable, you can assign it like this:

List<string> values;
values = new() { "single value" };

And finally, if you are using it in a method that returns a known type, you can return it like this:

public static List<T> SingleItemList<T>( T value )
{
    return new() { value };
}

Source: new-operator@learn.microsoft.com

pekaaw
  • 2,309
  • 19
  • 18
1

If someone landed on this page and trying to add object instead of string, then this worked for me.

new List<myObj> { new myObj{propertName=propstryValue }
, new myObj{propertName=propstryValue }, new myObj{propertName=propstryValue }
};
Ali
  • 1,015
  • 14
  • 40
-1

You need to create an inheritor from the List<> class

    public class SingletonList<T> : List<T>
    {
        public SingletonList(T element) : base(1)
        {
            this.Add(element);
        }
    }

and you can use it instead of the base List<> class

var singletonList = new SingletonList<string>("Hello World!");