如何将 C# 的 null 状态转换为 List<T> 到 List<T?>?

3

我正在C#的可空上下文中使用可空引用类型

我使用SelectList<string>转换为一个新的List<string?>,然后通过Where过滤掉null值,但底层类型仍然是List<string?>

strings = strings
    .Select(s => method.ThatReturnsNullableString(s))
    .Where(s => s is not null)
    .ToList();

当我尝试将其用作 List<string> 时,会收到 CS8619 编译器警告。一个简单的解决方案是使用! null-forgiving operator,这样警告就会消失,但我尽量少使用这种方法。
另一种解决方案是使用 .Cast<string>,但我认为这没有必要增加运行时开销。
我是否没有充分证明集合是类型为 string,还是有什么我不知道的事情?

请在查询中输入完整的类型,并包括 method.ThatReturnsNullableString(s) 的签名。 - Enigmativity
var strings = strings 是无效的 C# 代码。请给我们真正的代码。 - Enigmativity
2
而且对于 .Cast<string>() 没有额外的开销,因为你必须这样做。 - Enigmativity
Where方法不会改变类型。 - Jodrell
@Enigmativity 抱歉,我试图创建一个与我的实际代码分离的最小示例。我已经修改了我的示例以匹配@Muhammad Sulaiman的答案。至于完整类型,strings是一个List<string?>,示例方法可能类似于string Method(string? s) - aes
3个回答

9

.Where(s => s is not null)将忽略null值并保留string?类型的项,因此结果将是List<string?>类型。

使用.OfType<string>(),它将跳过空值并将string?强制转换为字符串,这相当于.Where(s => s is not null).Cast<string>()

strings = strings
    .Select(s => method.ThatReturnsNullableString(s))
    .OfType<string>()
    .ToList(); // List<string>

请在发布前测试您的代码。它是无效的C#。 - Enigmativity
一般来说,这不是 OfType 的作用。您明确声明了结果类型,如果源序列更改其类型,则结果不会更改。通过这种方法,您可能会无意中过滤掉不是 null 的内容。 - Antonín Lejsek
@MuhammadSulaiman - 没有什么比测试你的代码更好了。还有一个语法错误。 - Enigmativity
@MuhammadSulaiman - 另外,由于问题涉及到newStrings变量的最终类型,我建议不要使用var - Enigmativity
@AntonínLejsek 在这种情况下,我的列表仅包含string,但我感谢您的评论。您会推荐使用null-forgiving !,还是您有不同的想法? - aes

1

我认为Jodrell有一个很好的想法,这是一个值得开发扩展的模式。但我会使用更简单的API。

strings = strings
    .Select(s => methodThatReturnsNullableString(s))
    .SkipNulls()                
    .ToList();

扩展代码:
public static IEnumerable<T> SkipNulls<T>(this IEnumerable<T?> source)
{
    foreach (var item in source)
    {                
        if (item is not null)
        {
            yield return item;
        }
    }
}

0

我认为一种更简洁的扩展方法是:

public static IEnumerable<T> Denullify<T>(this IEnumerable<T?> source)
{
    foreach (var item in source)
    {
        if (item is T value)
        {
            yield return value;
        }
    }
}

这段代码:

Console.WriteLine(String.Join(", ", new string?[] { "A", null, "B", }));
Console.WriteLine(String.Join(", ", new string?[] { "A", null, "B", }.Denullify()));

...产生:

A, , B
A, B

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