C#复合if与带fall-through的switch中模式匹配变量使用问题
这不是模式匹配本身的限制,是C#的明确赋值规则的强制要求:
- 对于带
||的if条件:逻辑或的短路特性会导致只要任意一个分支满足,其余分支就不会执行。你写的if (currentShape is ITable table || currentShape is AutoShape autoShape)中,如果匹配的是ITable,那autoShape从未被赋值;如果匹配的是AutoShape,那table从未被赋值。编译器不允许使用未明确赋值的局部变量,所以会抛出CS0165错误。 - 对于带fall-through的switch语句:多个case共享同一段执行逻辑时,你无法确定运行时到底命中了哪一个case,其余case对应的模式变量同样处于未赋值状态,所以也无法直接使用。
以下是两种可行的实现方案:
方案1:拆分分支单独处理(最推荐)
把公共逻辑拆分到每个匹配分支中,此时每个分支的模式变量肯定已经完成赋值,不会触发编译错误。
if语句写法:
if (currentShape is ITable table) { // 此处可直接使用table变量 } else if (currentShape is AutoShape autoShape) { // 此处可直接使用autoShape变量 }
switch语句写法:
void Foo(object o) { string bar = string.Empty; switch (o) { case int i: bar = i.ToString(); break; case string s: bar = s; break; case Guid g: bar = g.ToString(); break; } }
如果逻辑足够简单,还可以用switch表达式进一步简化代码:
string bar = o switch { int i => i.ToString(), string s => s, Guid g => g.ToString(), _ => string.Empty };
方案2:预先声明变量初始化(符合你提到的思路)
如果确实需要把逻辑写在同一个公共块里,可以提前声明对应变量,先赋值为null(值类型要声明为可空类型),再在条件里完成赋值,后续做空值检查后即可使用:
// 预先声明并初始化 ITable table = null; AutoShape autoShape = null; if ((currentShape is ITable t && (table = t) != null) || (currentShape is AutoShape a && (autoShape = a) != null)) { if (table != null) { // 处理table逻辑 } else if (autoShape != null) { // 处理autoShape逻辑 } }
switch场景的类似实现:
void Foo(object o) { int? i = null; string s = null; Guid? g = null; switch (o) { case int tempI: i = tempI; break; case string tempS: s = tempS; break; case Guid tempG: g = tempG; break; default: return; } string bar = i?.ToString() ?? s ?? g?.ToString(); }
内容的提问来源于stack exchange,提问作者rory.ap
相关产品推荐
相关产品推荐

