C#集合初始化器 - 是否可以基于条件选择性地添加元素?

5

现在我的代码看起来是这样的:

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

是否有更简洁的方法在一行代码中创建一个列表,并可选地添加一个元素?


也许你可以考虑封装List<T>,并在其中重载Add(T)方法并加入条件。 - MaLiN2223
7
如果你只能用一个简单的语句来表达,那么这可能是最好的做法。如果你经常这样做,你可以添加一个扩展方法来从可空对象创建集合。 - Lee
@Lee,扩展方法听起来其实不是个坏主意。 - Dmytro Shevchenko
5个回答

2
我会使用类扩展方法来解决这个问题,代码如下:
public static void AddIfNotNull<T>(this List<T> list, T? value) where T : struct
{
    if(value != null)
    {
        list.Add(value.Value);
    }
}

那么它可以像这样使用:

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

也许不像你的提议那样"巧妙"(也不是一行代码),但在我看来,这种写法更易读、易懂。如果希望将其用作一行代码,可以修改扩展方法的返回类型为列表。这样就可以像这样使用:var ids = new List<Guid>().AddIfNotNull(projectId);

1
这段代码无法编译,因为TGuid,但projectIdGuid?。如果你要创建一个扩展方法,最好实现期望的行为,即函数T? -> List<T> - Lee

2

另一个扩展方法的想法(名称肯定可以改进,也许是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>();
    }
}

使用方法:

Guid? projectId = null;

List<Guid> projectIds = projectId.SingletonList(); // empty list

1

这很简洁,但另一种选择是使用LINQ:

var ids = new[] { projectId }.Where(x => x.HasValue).Select(x => x.Value).ToList();

4
它的长度几乎相同,并且隐藏了代码的意图。 - Yacoub Massad
你可能节省了2个字符,但是如果我在一个项目中阅读这段代码,我会认为有一些复杂的查询操作。我不会理解原始意图。 - Yacoub Massad
如果原始问题确实是用例,那么我可能不会这样做。但是LINQ解决方案更加通用,允许您筛选零个或多个可空值,并仅选择非空值,以防您发现自己处于可能不想完全执行的情况中。这完全取决于您的情况。 - Joe Enos

1
这可能不是一个好主意,但是在C# 6中,集合初始化器也适用于Add()作为扩展方法的情况
这意味着你可以像这样编写扩展Add()方法:
public static void Add<T>(this List<T> list, T? item) where T : struct
{
    if (item.HasValue)
    {
        list.Add(item.Value);
    }
}

然后这段代码将会实现你想要的功能:
var list = new List<Guid> { projectId };

请注意,这仅适用于值类型(由于 T/T? 的区别),并且没有简单的方法使其适用于引用类型。
此外,我会觉得上面的那行代码非常令人惊讶,更简洁并不总是更好。这就是为什么我实际上不会使用这段代码的原因。

谢谢!现在我想了想,你说得对,短并不总是更好。 - Dmytro Shevchenko
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Joe Enos
@JoeEnos 说这不好两次,难道还不够吗? :-) - svick

0
如果您选择使用扩展方法,代码可能如下所示:

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

如果需要,您必须为引用类型(where T : class)构建第二个扩展方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接