当用作通用类型时,可为空的枚举类型不能分配为null

该隐

我使用的是C#9,遇到了这个奇怪的问题,因此我在下面写了一个简单的示例来演示它。我需要将可为空的枚举的值设置为null,但是通过泛型类型执行此操作时会出现错误。如果我将枚举类型硬编码到类中,则可以正常工作,所以我不确定为什么将相同类型用作泛型时它不起作用。似乎TOption?将其视为TOption忽略了可空的部分,这将使此错误变得有意义,因为它将尝试将null分配给不可为空的值类型。

这是可空类型,值类型和编译器假设之间的奇怪冲突吗?不应TOption?与将Option?whenOption用作泛型类型完全一样地对待吗?

请注意,TOption在实际情况下,我不能约束为值类型来解决此问题,并且我认为此约束不是必需的。我不需要TOption是值类型,我只需要该字段可为空即可-不管它是类还是结构。

关于放入Option?for TOption,我仍然需要将其视为不可为空的字段。因此,我无法做到这一点,我需要泛型中的实际类型,但我需要能够区分该类型的不可为null和可为null的字段-与作为结构或类的类型无关。我应该指出,我使用的是可为空的引用类型,因此除非使用进行了指定,否则将类视为不可为空?

public class Program
{
    public static void Main(string[] args)
    {
        var test = new Test<Option>();
        test.Option1 = null;
        test.Option2 = null; // Cannot convert null to 'Program.Option' because it is a non-nullable value type
    }

    public enum Option { A, B, C }

    public class Test<TOption>
    {
        public Option Option0 { get; set; }
        public Option? Option1 { get; set; }
        public TOption? Option2 { get; set; }
    }
}
清扫器

失败的原因与我在这里所作的解释非常相似在这种情况下,有一种解决方法,但在您的情况下,您实际上需要一个可为空的值类型,这使得这几乎不可能。

T?对CLR来说,意味着两个完全不同的内容T如果T是值类型,则表示Nullable<T>如果T是引用类型,就CLR而言T?实际上与T(具有某些属性)相同

因此,当编译器正在编译您的代码时,它将表示哪种类型Option2换句话说,如果您typeof(Test<>)使用反射检查了(注意开放类型)的成员,那么Option2属性的类型是什么?

在你的理想世界中,你想Option2成为的类型Nullable<TOption>时,TOption是值类型,并且类型TOptionTOption是引用类型。但是,如果我们要检查的属性的typeof(Test<>)类型,我们将得到哪种类型?不能两者都可以吗?

实际上,编译器选择TOption的类型Option2并将其类型视为Option2可为空,但也要记住,它也可以是不可为空的值类型。

这就是为什么仅凭说就不可能实现“可空值和引用类型”的原因T?

一个相当丑陋的解决方法是创建自己的Nullable<T>不限制T值类型的方法:

struct MyNullable<T> where T: notnull {
    private T value;
    
    public bool HasValue {
        get;
    }
    
    public T Value { 
        get {
            if (HasValue) {
                return value;
            } else {
                throw new InvalidOperationException("Value is not present!");
            }
        } 
    }
    
    public MyNullable(T t) {
        value = t;
        HasValue = t != null;
    }
}

现在您可以执行以下操作:

public class Test<TOption>
{
    public Option Option0 { get; set; }
    public Option? Option1 { get; set; }
    public MyNullable<TOption> Option2 { get; set; }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

PHP类型属性批量声明不能将null分配给可为空的字段

来自分类Dev

可为空的通用引用类型

来自分类Dev

装箱的可为空的基础类型可以强制转换为枚举,但装箱的枚举类型不能强制转换为可空类型

来自分类Dev

类型“ MyObject”必须是不可为空的值类型,以便在通用类型或方法“ Nullable <T>”中将其用作参数“ T”

来自分类Dev

通用类型可为null和ToString

来自分类Dev

当用作通用接口参数时,F#类型系统为什么对unit进行不同的处理?

来自分类Dev

“ System.Guid”失败,因为实例化值为null。结果类型的通用参数或查询必须使用可为空的类型

来自分类Dev

C#8可为空和不可为空的引用类型-仅当输入为可为空时才可为可输出

来自分类Dev

C#8可为空和不可为空的引用类型-仅当输入为可为空时才可为可输出

来自分类Dev

类型为<T>的类,其类型为<T>的可为空

来自分类Dev

通用方法-类型不能用作类型参数

来自分类Dev

Rust将枚举返回为通用类型

来自分类Dev

如何检查Dart NNBD中的通用类型是否可为空?

来自分类Dev

分配为空引用类型

来自分类Dev

当用作参数时,无法推断Action委托的返回类型

来自分类Dev

当用作参数时,无法推断Action委托的返回类型

来自分类Dev

确定类型是否为枚举类型的通用列表

来自分类Dev

为通用类型分配默认值

来自分类Dev

推断类型为可为空的集合,但预期为不可为空的集合

来自分类Dev

通用枚举类型防护

来自分类Dev

类型“ T”不能用作通用类型或方法中的类型参数“ T”

来自分类Dev

类型不能在通用类型或方法中用作类型参数“ T”-为什么?

来自分类Dev

Ninject ASP.NET标识在通用类型或方法中,类型“ .....”不能用作类型参数“ TImplementation”

来自分类Dev

从可为空的类型中提取不可为空的类型定义

来自分类Dev

哪些Unity类型可为空?

来自分类Dev

PHP可为空的类型声明

来自分类Dev

通用类型的托管记录产生编译时错误“类型参数'T'必须为非空值类型”

来自分类Dev

强制转换为值类型'Enum'失败,因为实例化值为null。结果类型的参数或查询必须使用可为空的类型

来自分类Dev

不能将类型接口{}用作分配中的类型人:需要类型声明

Related 相关文章

  1. 1

    PHP类型属性批量声明不能将null分配给可为空的字段

  2. 2

    可为空的通用引用类型

  3. 3

    装箱的可为空的基础类型可以强制转换为枚举,但装箱的枚举类型不能强制转换为可空类型

  4. 4

    类型“ MyObject”必须是不可为空的值类型,以便在通用类型或方法“ Nullable <T>”中将其用作参数“ T”

  5. 5

    通用类型可为null和ToString

  6. 6

    当用作通用接口参数时,F#类型系统为什么对unit进行不同的处理?

  7. 7

    “ System.Guid”失败,因为实例化值为null。结果类型的通用参数或查询必须使用可为空的类型

  8. 8

    C#8可为空和不可为空的引用类型-仅当输入为可为空时才可为可输出

  9. 9

    C#8可为空和不可为空的引用类型-仅当输入为可为空时才可为可输出

  10. 10

    类型为<T>的类,其类型为<T>的可为空

  11. 11

    通用方法-类型不能用作类型参数

  12. 12

    Rust将枚举返回为通用类型

  13. 13

    如何检查Dart NNBD中的通用类型是否可为空?

  14. 14

    分配为空引用类型

  15. 15

    当用作参数时,无法推断Action委托的返回类型

  16. 16

    当用作参数时,无法推断Action委托的返回类型

  17. 17

    确定类型是否为枚举类型的通用列表

  18. 18

    为通用类型分配默认值

  19. 19

    推断类型为可为空的集合,但预期为不可为空的集合

  20. 20

    通用枚举类型防护

  21. 21

    类型“ T”不能用作通用类型或方法中的类型参数“ T”

  22. 22

    类型不能在通用类型或方法中用作类型参数“ T”-为什么?

  23. 23

    Ninject ASP.NET标识在通用类型或方法中,类型“ .....”不能用作类型参数“ TImplementation”

  24. 24

    从可为空的类型中提取不可为空的类型定义

  25. 25

    哪些Unity类型可为空?

  26. 26

    PHP可为空的类型声明

  27. 27

    通用类型的托管记录产生编译时错误“类型参数'T'必须为非空值类型”

  28. 28

    强制转换为值类型'Enum'失败,因为实例化值为null。结果类型的参数或查询必须使用可为空的类型

  29. 29

    不能将类型接口{}用作分配中的类型人:需要类型声明

热门标签

归档