如何在C#对象类型Switch中实现贯穿,统一处理多类型实例?
解决switch类型模式中多类型共享处理逻辑的问题
这个问题我之前也遇到过,核心是编译器的静态检查和switch类型模式的变量绑定规则在作祟。咱们一步步来看怎么解决:
最优方案(C# 9.0+):使用or合并类型模式
从C#9开始,类型模式支持用or运算符合并多个类型,并且可以绑定到同一个变量名,完美解决你的需求,完全不需要fallthrough:
switch (myObject) { // ... 其他case分支 case MyObjectType1 or MyObjectType2 or MyObjectType3 or MyObjectType4 myObjectInstance: // 这里myObjectInstance会自动绑定到匹配的类型实例 HandleMyObjectTypes(myObjectInstance); break; }
这个写法既简洁又安全,编译器会确保myObjectInstance是已赋值的——因为只有匹配到其中一个类型时,才会进入这个case分支。前提是MyObjectType1到MyObjectType4都兼容HandleMyObjectTypes的参数类型(比如继承自同一个基类、实现同一个接口,或者参数是object类型)。
兼容旧版本C#的方案(C# 8.0及更早)
如果你的项目还在使用C#8或更早版本,没法用or合并类型,可以用when从句配合类型检查:
switch (myObject) { // ... 其他case分支 case object when myObject is MyObjectType1 or MyObjectType2 or MyObjectType3 or MyObjectType4: // 已经通过when确认类型,直接转换即可 var myObjectInstance = (MyBaseType)myObject; // 换成你的基类/接口类型 HandleMyObjectTypes(myObjectInstance); break; }
或者更稳妥一点用as转换(虽然这里因为已经做了类型检查,as不会返回null):
var myObjectInstance = myObject as MyBaseType; HandleMyObjectTypes(myObjectInstance);
为什么你原来的写法会报错?
你尝试用??合并变量的思路逻辑上是对的,但编译器的静态分析不认可:在fallthrough的case分支里,只有实际匹配到的那个case的变量是被赋值的,其他变量都处于未赋值状态。编译器没法静态推断出“至少有一个变量肯定被赋值”,所以会抛出「未赋值的局部变量」错误。
退而求其次的方案:重复调用(不推荐,但应急可用)
如果以上方案都没法用,也可以每个case单独调用方法,虽然代码重复,但能满足需求:
switch (myObject) { // ... 其他case分支 case MyObjectType1 obj: HandleMyObjectTypes(obj); break; case MyObjectType2 obj: HandleMyObjectTypes(obj); break; case MyObjectType3 obj: HandleMyObjectTypes(obj); break; case MyObjectType4 obj: HandleMyObjectTypes(obj); break; }
如果不想重复代码,还可以在方法内部定义一个局部方法来包装调用:
// 方法内部定义局部方法 void Handle(T obj) where T : MyBaseType => HandleMyObjectTypes(obj); switch (myObject) { // ... 其他case分支 case MyObjectType1 obj: Handle(obj); break; // 其他case同理 }
内容的提问来源于stack exchange,提问作者user4593252
相关产品推荐
相关产品推荐

