Dart运行时类型分发最优实现:能否用if运算符仅处理副作用?
Dart运行时类型分发的简洁实现与三目运算符副作用疑问
我希望找到最简洁的Dart运行时类型分发并执行对应操作的实现方式,目前的代码片段如下:
if (mmodel is _ChangeReq<T>) { mmodel.base.update((list) => list[mmodel.index] = newItem); } else if (mmodel is _AddReq<T>) { mmodel.growable.updateSuperDuper((list) => list.add(newItem)); }
(未简化代码以便展示真实场景)
我不太喜欢这种if-else结构,更倾向于使用switch语句,但当时Dart不支持类模式匹配,因此尝试改写为基于三目运算符的代码:
(mmodel is _ChangeReq<T>) ? mmodel.base.update((list) => list[mmodel.index] = newItem) : (mmodel is _AddReq<T>) ? mmodel.growable.updateSuperDuper((list) => list.add(newItem)) : throw ArgumentError("Unknown class ${mmodel.runtimeType}");
这种写法作为替代方案可行,但存在疑问:我仅用三目运算符实现副作用,并未使用它的返回结果,这是否意味着代码可能会被编译器优化掉?
核心问题解答
Dart语言规范明确要求,所有带有可见副作用的表达式必须被执行,无论是否使用表达式的返回结果。三目运算符属于表达式,其分支中执行的方法调用(如update、updateSuperDuper这类修改状态的操作)、抛出异常都属于可见副作用,编译器不会优化掉这些分支的执行逻辑。
编译器仅会消除无任何可见副作用的代码(比如纯粹计算但未使用结果的情况),而有状态修改、IO操作、抛出异常这类明确有副作用的操作,都会被保留执行。
更优写法建议
如果使用Dart 3.0及以上版本,推荐使用switch模式匹配,这是官方支持的类型分发方式,代码可读性更高:
switch (mmodel) { case _ChangeReq<T> req: req.base.update((list) => list[req.index] = newItem); break; case _AddReq<T> req: req.growable.updateSuperDuper((list) => list.add(newItem)); break; default: throw ArgumentError("Unknown class ${mmodel.runtimeType}"); }
内容的提问来源于stack exchange,提问作者Stepan Dyatkovskiy
相关产品推荐
相关产品推荐

