You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何处理依赖枚举值的可空返回?替代空原谅运算符的方案

问题

我有一个返回元组(MyEnum, Package?)的方法:仅有一种MyEnum枚举值对应Package非空,其余所有枚举值均对应Package为null。示例代码如下:

(MyEnum response, Package? package) MyMethod()
{
    if (Today == NiceDay)
    {
        return (MyEnum.Happy, new Package("I'm happy!"));
    }
    if (Today == RainyDay)
    {
        return (MyEnum.Pensive, null);
    }
    if (Today == SnowyDay)
    {
        return (MyEnum.Cold, null);
    }
}

当尝试直接访问MyMethod().package.message时,编译器会触发空引用警告。我了解空原谅运算符,但认为这只是临时解决方案。请问能否让编译器根据MyMethod().response是否为MyEnum.Happy,自动识别package是否非空?还是只能使用空原谅运算符处理该场景?

解决方案

当然可以让编译器自动识别package的非空性,不需要依赖空原谅运算符,推荐两种方案:

1. 使用模式匹配(C# 8.0+)

利用C#的模式匹配语法,直接在判断枚举值的同时解构元组,编译器会自动推断此时package非空:

// 方式1:先获取结果再判断
var result = MyMethod();
if (result.response == MyEnum.Happy)
{
    // 编译器确认此处package非空,无警告
    Console.WriteLine(result.package.Message);
}

// 方式2:直接在条件中解构匹配
if (MyMethod() is (MyEnum.Happy, var package))
{
    Console.WriteLine(package.Message); // 无空引用警告
}

这种方式不需要修改原方法的返回类型,直接通过语法让编译器理解枚举值与对象非空性的关联。

2. 自定义带空校验属性的结构体

如果需要更严谨的类型约束,可以把元组替换为自定义结构体,通过[NotNullWhen]属性明确告诉编译器:当Response为MyEnum.Happy时,Package一定非空。

using System.Diagnostics.CodeAnalysis;

public struct MyMethodResult
{
    public MyEnum Response { get; }
    
    // 标注:当Response等于MyEnum.Happy时,Package不为null
    [NotNullWhen(ReturnValue = MyEnum.Happy)]
    public Package? Package { get; }

    public MyMethodResult(MyEnum response, Package? package)
    {
        Response = response;
        Package = package;
    }

    // 可选:添加解构方法,保持和原元组类似的使用体验
    public void Deconstruct(out MyEnum response, out Package? package)
    {
        response = Response;
        package = Package;
    }
}

// 修改原方法返回自定义结构体
public MyMethodResult MyMethod()
{
    if (Today == NiceDay)
    {
        return new MyMethodResult(MyEnum.Happy, new Package("I'm happy!"));
    }
    return Today == RainyDay 
        ? new MyMethodResult(MyEnum.Pensive, null) 
        : new MyMethodResult(MyEnum.Cold, null);
}

使用时,只要判断Response为MyEnum.Happy,编译器就会自动识别Package非空:

var result = MyMethod();
if (result.Response == MyEnum.Happy)
{
    Console.WriteLine(result.Package.Message); // 无警告
}

为什么原元组不行?

原生元组的两个元素是独立的类型成员,编译器无法建立“枚举值与对象非空性”的关联关系,因此无法自动推断。而上述两种方案都是通过语法或属性给编译器补充了这层关联信息。

内容的提问来源于stack exchange,提问作者Artur S.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 23:50:41