使用Linq的Where/Select过滤掉null并将类型转换为非null不能被用作扩展方法 [英] Using Linq's Where/Select to filter out null and convert the type to non-nullable cannot be made into an extension method

查看:365
本文介绍了使用Linq的Where/Select过滤掉null并将类型转换为非null不能被用作扩展方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有

List<MyObject?> list = ...;

我想将其转换为List<MyObject>,但是我无法删除可为空的引用.

I want to turn it into List<MyObject>, but I have not been able to drop the nullable reference.

下面是MCVE.在我的项目中,我将可为空的参考警告转为错误,因此下面的注释行将无法编译.

Below is an MCVE. In my project I have nullable reference warnings turned to errors, so the commented out line below will not compile.

如果我执行.Where(e => e != null).Select(e => e!),那么在最新的.NET Core 3.1.100中就可以了,但是我无法将其提取为扩展方法.

If I do .Where(e => e != null).Select(e => e!) then it will be fine in the latest .NET Core 3.1.100, however I cannot extract this into an extension method.

我尝试添加此扩展方法

    public static IEnumerable<T> NotNull<T>(this IEnumerable<T> enumerable)
    {
        return enumerable.Where(e => e != null).Select(e => e!);
    }

但是,它不会将IEnumerable<MyObject?>转换为IEnumerable<MyObject>,我不确定为什么.这导致我出现类似以下错误:

However it will not convert IEnumerable<MyObject?> to IEnumerable<MyObject> and I am unsure why. This leads me to an error like:

[CS8619]引用类型为列表"类型的值中的空性与目标类型列表"不匹配.

[CS8619] Nullability of reference types in value of type 'List' doesn't match target type 'List'.

有什么办法可以使上述NotNull函数正常工作吗?

Is there a way I can make the NotNull function above work somehow?

推荐答案

您必须将扩展方法更新为以下内容

You have to update your extension method to the following

public static IEnumerable<T> NotNull<T>(this IEnumerable<T?> enumerable) where T : class
{
    return enumerable.Where(e => e != null).Select(e => e!);
}

这里的要点是您要将可空引用的IEnumerable转换为不可空引用,因此必须使用IEnumerable<T?>.需要where T : class通用约束来帮助编译器区分可空引用类型和Nullable<T>结构,因为您可以阅读

The point here is that you are converting the IEnumerable of nullable references to not nullable ones, therefore you'll have to use IEnumerable<T?>. where T : class generic constraint is needed to help the compiler distinguish between nullable reference type and Nullable<T> struct, as you can read here

因为此问题在nullable的具体表示之间 引用类型和可为空的值类型,T?的任何使用也必须 要求您将T限制为classstruct.

Because of this issue between the concrete representations of nullable reference types and nullable value types, any use of T? must also require you to constrain the T to be either class or struct.

之后,将在没有任何警告的情况下编译以下行

After that the following lines will be compiled without any warnings

var list = new List<MyObject?>();
IEnumerable<MyObject> notNull = list.NotNull();

这篇关于使用Linq的Where/Select过滤掉null并将类型转换为非null不能被用作扩展方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆