Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# collection initializer – is it possible to add an element optionally, based on a condition?

Tags:

c#

Right now my code looks like this:

var ids = projectId.HasValue ? new List<Guid> { projectId.Value } : new List<Guid>();

Is there a more succinct way of creating a list in one line of code, with one element added optionally?

like image 812
Dmytro Shevchenko Avatar asked Jan 22 '16 15:01

Dmytro Shevchenko


3 Answers

Another idea for an extension method (the name could definitely be improved, maybe PossiblyCreateSingletonList?):

public static class NullableExtensions
{
    public static List<T> SingletonList<T>(this Nullable<T> item) where T : struct
    {
        return item.HasValue ? new List<T> { item.Value } : new List<T>();
    }
}

Usage:

Guid? projectId = null;

List<Guid> projectIds = projectId.SingletonList(); // empty list
like image 73
Andrew Whitaker Avatar answered Sep 28 '22 14:09

Andrew Whitaker


I would solve this using a extension method like this:

public static void AddIfNotNull<T>(this List<T> list, T? value) where T : struct
{
    if(value != null)
    {
        list.Add(value.Value);
    }
}

Than it could be used like this:

var ids = new List<Guid>();
ids.AddIfNotNull(projectId);

Maybe not as "crafty" (and not a one-liner) as your proposal, but in my opinion it is much easier to read and understand. If desired to be used as a one-liner you could modify the return type of the extension to be the list. That would make it possible to be used something like var ids = new List<Guid>().AddIfNotNull(projectId);

like image 43
Simon Karlsson Avatar answered Sep 28 '22 16:09

Simon Karlsson


This probably isn't a good idea, but in C# 6, collection initializers also work when Add() is an extension method.

This means you can write the extension Add() like this:

public static void Add<T>(this List<T> list, T? item) where T : struct
{
    if (item.HasValue)
    {
        list.Add(item.Value);
    }
}

And then this code will do what you want:

var list = new List<Guid> { projectId };

Note that this will only work for value types (because of the T/T? distinction) and there is no simple way to make it work for reference types.

Also, I would find the line above very surprising, being more succinct is not always better. Which is why I actually wouldn't use this code.

like image 20
svick Avatar answered Sep 28 '22 16:09

svick