【问题标题】:Convert IEnumerable<T?> to IEnumerable<T>将 IEnumerable<T?> 转换为 IEnumerable<T>
【发布时间】:2021-02-04 00:21:48
【问题描述】:

我希望能够获取可空类型 T? 的列表,并删除任何空值,留下 T 类型。例如:

        List<int?> xs = new List<int?>() {1, 2, 3};
        
        // this method works
        IEnumerable<int> xs2 = xs.Select(x => x ?? 0);
        
        // this method does not
        IEnumerable<int> xs3 = xs.Where(x => x != null);

我很欣赏 C# 无法推断列表的类型,以便能够判断列表中没有空值。但我正在努力寻找最好的方法来做到这一点,而不仅仅是像这样进行明确的演员:

IEnumerable<int> xs3 = xs.Where(x => x != null).Select(x => (int)x);

我遇到的问题是,如果Where 语句不存在,那么代码仍然会通过类型检查,但会出现运行时错误。有没有办法在 C# 中做到这一点,这样,在编译时,我可以保证列表的类型不可为空,并且它不包含空值?

dotnetfiddle

理想情况下,我希望以通用方式执行此操作(但我有一个单独的问题)。

我设法找到了this question,它提供了一种通过将空值转换为类型值来转换值的好方法。

有没有办法做到这一点?

【问题讨论】:

  • 执行此操作的规范方法是.Cast&lt;int&gt;()(或一般情况下的.Cast&lt;T&gt;())。但是,这只是您的 Select 的语法糖,所以我不确定您是否将其视为答案。
  • 一个简单的xs.OfType&lt;int&gt;();?
  • @Ralf 是的!完美解决,不知道有没有
  • @Heinzi .Cast&lt;int&gt;() 在遇到null 时会抛出。有时这正是你想要的,但它会改变这里的行为
  • @AluanHaddad:我的意思是CastSelect 的替代品,即.Where(x =&gt; x != null).Cast&lt;int&gt;()。 Ralf 完全正确,当然,OfType 更加简洁。

标签: c#


【解决方案1】:

你可以使用.Value:

IEnumerable<int> xs3 = xs.Where(x => x != null).Select(x => x.Value);

【讨论】:

  • 感谢您的回答 - 我相信 OfType 在这种情况下提供了更好的解决方案,因为似乎使用 Value 选择仍然会在 null 上出现运行时异常(在示例中欣赏我已经过滤掉了空值,我真的很喜欢OfType,因为它不依赖于已经巧合过滤掉的空值)
  • 因为前面有x != null 过滤器,所以.Value 保证成功。除了x != null,您也可以使用Where(x =&gt; x.HasValue),这对Nullable&lt;T&gt; 的作用完全相同,并且更明显的是您正在处理Nullable&lt;T&gt;。有关详细信息,请参阅我链接到的页面。
  • 我个人在处理 nullable 时的偏好是使用 .HasValue 和 .Value 属性。
  • @PeterB 绝对 - 我的偏好是不依赖于已经过滤掉空值的代码的解决方案。可能是我需要改写问题。
  • 我不知道OfType&lt;&gt;()的这种行为,乍一看很奇怪,但有时很有用。
猜你喜欢
  • 1970-01-01
  • 2012-02-24
  • 1970-01-01
  • 2021-12-02
  • 1970-01-01
  • 2018-08-04
  • 1970-01-01
  • 2012-01-19
相关资源
最近更新 更多