Tuesday, April 5, 2011

Shortcut for creating single item list in C#

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?

Thanks.

From stackoverflow
  • 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");
    
  • 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", ... };
    
    Joel Coehoorn : put a 1 literal in the parentheses of the first option, so that storage for exactly one space is allocated rather than the default 10
    Jon Skeet : The default ends up being 4, I believe: new List { "Hello" }.Capacity == 4
  • You can also do

    new List<string>() { "string here" };
    
  • Michael's idea of using extension methods leads to something even simpler:

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

    So you could do:

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

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

    M4N : I'm also not sure I like it: isn't this a "strange" extension of the string type (for example) ?
    Ryan Ische : 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.
    Jon Skeet : @Martin: It's a strange extension of *every* type. This is generally discouraged, but it's an interesting general idea.
    Michael Meadows : 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));
  • I would just do

    var list = new List<string> { "hello" };
    
  • 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.)

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

  • 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?

0 comments:

Post a Comment