如果默认泛型属性可以为空,并且泛型类型不受任何限制,为什么不能用值NULL值填充该属性呢?

public class Class_0<TValue> where TValue : struct
{
    public TValue? Value { get; } = null; // is valid
}

public class Class_1<TValue> where TValue : class
{
    public TValue? Value { get; } = null; // is valid
}

public class Class_2<TValue>
{
    public TValue? Value { get; } = null;  // error
}

我需要属性能够是 struct 或类,并且始终用空值填充.我不能写这样的东西:where TValue : struct, class.

推荐答案

这种情况的发生是因为抽象存在漏洞.C#编译器方便的?语法掩盖了类型TValue? where TValue : classTValue? where TValue : struct是不兼容的CLR类型的事实.第一个只有TValue:引用类型上的可空注释不是CLR类型系统的一部分,而是作为编译器知道的一组属性实现的.第二个是泛型值类型Nullable<TValue>.给定像Class_2<TValue>这样的单个声明,编译器不能发出行为类似于两者的CLR泛型类型声明,因为在第一种情况下TValue?需要表示为!0,在第二种情况下需要表示为System.Nullable`1<!0>(IL语法!0引用活动泛型类型上下文的第一个泛型参数,在本例中为Class_2`1).那么,编译器做些什么呢?如果在ILDasm中打开您的示例,您将看到

public class Class_2<TValue>
{
    public TValue? Value { get; }
}

用一个属性和一个TValue类型的支持字段编译成泛型类型Class_2`1<TValue>,不带任何可为空性注释,即编译器只是放弃并忽略?(我使用的是.NET 8).这可能不是处理这种情况的理想方法,但它是唯一提供向后兼容性的方法.不幸的是,这意味着您不能编写一个C#泛型来做您想做的事情:您必须为引用和值类型参数分别声明,或者放弃内置的空性而手动实现它.

Csharp相关问答推荐

如何设置和接收自定义Visual Studio项目命令的参数

在包含空项的列表上使用具有断言T的摘要表

使用GeneratedComInterfaceProperty的.NET 8 COM类对于VB 6/SYS或ALEViewer不可见

错误NU 1301:无法加载源的服务索引

什么是通过反射创建类的泛型接口方法的正确方法?

不仅仅是一个简单的自定义按钮

图形API基于appid列表检索多个应用程序

可为空的泛型属性

有没有办法在WPF文本框中添加复制事件的处理程序?

在Windows Plesk上发布ASP.NET Core 7 Web API-错误:无法加载文件或程序集';Microsoft.Data.SqlClient';

C#动态设置ServerReport报表参数

使用动态键从请求体反序列化JSON

System.NotSupportdException:流不支持读取

如何从非异步任务中正确返回TypeResult

C#命名管道-编码错误?

Visual Studio 17.8.0制表符自动完成问题--三缩进

如何对特定异常使用Polly重试机制?

当要删除的子模型没有父模型的1:多属性时,如何告诉实体框架设置1:1 FK条目?

我什么时候不应该在Dispose中调用EgSuppressFinalize(This)?

根据运行时值获取泛型类型的字典