【发布时间】:2021-01-19 08:09:54
【问题描述】:
我使用的是 C# 9,但遇到了这个奇怪的问题,所以我在下面写了一个简单的示例来演示它。我需要将可空枚举的值设置为空,但是通过泛型类型执行此操作时出现错误。如果我将枚举类型硬编码到类中它可以正常工作,所以我不确定为什么当相同类型用作泛型时它不起作用。似乎TOption? 被视为TOption 忽略了可为空的部分,这将使此错误变得有意义,因为它会尝试将 null 分配给不可为空的值类型。
这是可空类型、值类型和编译器假设之间的奇怪冲突吗?当Option 用作泛型类型时,TOption? 不应该与Option? 完全相同吗?
请注意,我不能将TOption 约束为在我的实际情况下解决此问题的值类型,并且我认为此约束不是必需的。我不需要 TOption 成为值类型,我只需要该字段可以为空——不管它是类还是结构。
关于将Option? 放入TOption,我仍然需要将其视为不可为空的字段。所以我不能这样做,我需要泛型中的实际类型,但我需要能够区分该类型的不可空和可空字段——独立于结构或类的类型。我应该指出,我使用的是可为空的引用类型,因此除非用? 指定,否则类将被视为不可为空。
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; }
}
}
【问题讨论】:
-
可空值和引用类型是非常不同的事物类型。你不能表达“无论类型是值还是引用类型都可以为空”
-
"我认为这个约束应该是不必要的" - 你的想法和规范所说的是两件不同的事情
-
为了强调这一点,我建议您按照给出的答案中的建议修改
Test(限制为struct),并创建一个限制为class的Test2。编译两者,然后用 ILDASM 反编译。您会看到两者的代码不同。 -
@Damien_The_Unbeliever 如果我想要的在当前编译器中是不可能的,那很好,我只想确定我想要的理论上应该是可能的。
-
@Cains 这就是为什么所有人都回答和评论来解决你的枚举问题,乍一看......因为标题、代码和暴露的问题。而且你已经告诉了每个人这不合适。吨的 cmets 意味着问题需要的细节或清晰度(我不能再次投票)。因此,我删除了我的答案并投票赞成@.00110001。所以请看一下xyproblem.info。