升级至Sound Null Safety后,枚举转换函数空安全问题求助
我完全懂你升级到Sound Null Safety后的困扰——原来的枚举转换代码因为空值限制直接报错了,咱们来拆解问题并搞定它。
首先看你原来的代码核心问题:函数声明返回的是非空类型E,但orElse回调返回了null,这在空安全规则下是绝对不允许的,因为非空类型不能容纳null值。另外describeEnum(element!)里的!其实是多余的,枚举类型的元素本身就不可能为空,不需要强制解包。
下面给你几个适配空安全的解决方案,你可以根据自己的业务需求选:
方案1:允许返回空值(最直接的修改)
如果你的业务逻辑允许找不到匹配枚举时返回null,那只需要把函数的返回类型改成可空的E?,同时去掉多余的!就行:
E? valueToEnum<E>( dynamic value, List<E> enumValues, ) => enumValues.firstWhere( (E element) => describeEnum(element) == '$value', orElse: () => null, );
这样调用函数的时候,你需要处理返回值可能为空的情况(比如用?.或者if null运算符),符合空安全的要求。
方案2:强制返回非空值(两种子场景)
如果你的业务逻辑要求必须返回一个有效的枚举值,不能返回null,可以选下面两种方式:
子场景A:找不到时抛出异常
直接去掉orElse回调,这样当没有匹配项时,firstWhere会自动抛出StateError,函数保持返回非空的E:
E valueToEnum<E>( dynamic value, List<E> enumValues, ) => enumValues.firstWhere( (E element) => describeEnum(element) == '$value', // 去掉orElse,无匹配时抛出StateError );
适合那些“找不到枚举就属于异常情况”的场景,调用时可以用try/catch捕获异常。
子场景B:指定默认枚举值
新增一个必填的默认值参数,当找不到匹配项时返回这个默认值,确保返回值始终是非空的:
E valueToEnum<E>( dynamic value, List<E> enumValues, { required E defaultValue, }) => enumValues.firstWhere( (E element) => describeEnum(element) == '$value', orElse: () => defaultValue, );
调用的时候就需要传入默认值,比如:
// 假设你有个枚举叫ColorEnum final color = valueToEnum('red', ColorEnum.values, defaultValue: ColorEnum.blue);
为什么你之前的尝试没用?
你说在E后加?.并设值为''——这不对,因为''是字符串类型,和枚举类型E不兼容;给null加!的话,虽然编译时不会报错,但运行时null!本质还是null,当你把它赋值给非空的E类型变量时,还是会触发空指针错误,这是违背空安全设计初衷的。
内容的提问来源于stack exchange,提问作者thequickLearner

