Switch模式匹配fallback场景下,i32变量为何被判定为未赋值?
为什么switch case中的
i32会被判定为未赋值? 先把你的代码贴出来方便分析:
void Foo(object value) { switch (value) { case Int16 i16: case Int32 i32: // Do something with i32 break; } }
你的疑惑完全合理——明明i32的case分支存在,为啥编译器还会认为它可能未赋值?核心原因在于C#模式匹配的case变量赋值规则,以及编译器对代码路径的严格检查:
case变量的赋值前提
模式匹配里的case变量(比如这里的i16和i32),只有当对应的模式完全匹配成功时,才会被赋值。换句话说:- 只有当
value是Int32类型时,i32才会被成功赋值; - 如果
value是Int16类型,程序会进入第一个case Int16 i16,因为没有break,会直接“贯穿”(fall through)到第二个case的代码块,但此时Int32 i32的模式匹配是失败的——value根本不是Int32,所以i32不会被赋值。
- 只有当
编译器的明确赋值检查
C#编译器要求,在使用任何变量之前,所有可能到达该使用位置的代码路径中,变量都必须被明确赋值。在你的代码里,存在一条合法的代码路径:value是Int16→ 进入第一个case → 贯穿到第二个case的代码块 → 尝试使用i32,但此时i32完全没有被赋值。编译器捕捉到了这条路径,所以会报错提示i32未被赋值。
修复方案参考
如果你想把Int16和Int32统一处理,有两种常见方式:
- 给第一个case添加
break,手动转换类型后处理:void Foo(object value) { switch (value) { case Int16 i16: int i32 = i16; // 把short转成int统一处理 // Do something with i32 break; case Int32 i32: // Do something with i32 break; } } - 使用C# 9+的联合模式,简化分支逻辑:
void Foo(object value) { switch (value) { case short i16 or int i32: int num = value is short s ? s : i32; // Do something with num break; } }
内容的提问来源于stack exchange,提问作者Jan Vargovsky
相关产品推荐
相关产品推荐

