根据https://blogs.msdn.microsoft.com/dotnet/2017/03/09/new-features-in-c-7-0/,对类型使用的switch
语句是对订单敏感的:
案件条款的顺序现在很重要:就像catch条款一样 案件条款不再必然是不相交的,第一个 这些比赛被选中了。
如果类型上使用的switch
语句遵循顺序,我认为它只不过是一个if-else-if
链。这个页面https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/switch也提示了这一点:首先它给出了关于类型的switch
语句的示例,然后它说“没有模式匹配,这段代码可能写成如下”并显示{{ 1}}链。
但在我的场景中,类型在继承或接口实现方面是不相关的,因此案例肯定是不相交的。
编译器是否会发现这一点并自动将if-else-if
语句转换为查找表?
如果没有,有没有办法强制编译器将其转换为查找表?
情景:
我正在将xsd.exe从xsd xml架构创建的自动生成的对象结构中的数据解析为我自己的数据结构。因为xsd模式使用了很多选择语句,所以我经常最终使用这种模式:
switch
我最近决定优化性能,这就是我对static IContent ParseContent(object c)
{
// Because of the choice statements in the xsd, the object c can be an instance
// of many different (auto-generated) classes which are not related to each other
// in terms of inheritance or interface implementation.
if (c is class1 c1) // class1 is an auto-generated class from the xsd schema
return ParseClass1(c1);
else if (c is class2 c2) // class2 is an auto-generated class from the xsd schema
return ParseClass2(c2);
....
else if (c is class20 c20) // class20 is an auto-generated class from the xsd schema
return ParseClass20(c20);
else
throw new ArgumentException(...);
}
static MyClass1 ParseClass1(class1 c1) { ... } // MyClass1 implements IContent
...
static MyClass20 ParseClass20(class20 c20) { ... } // MyClass20 implements IContent
的机制感兴趣的原因。
答案 0 :(得分:1)
- 编译器会发现这个并自动将switch语句转换为查找表吗?
醇>
不,因为它无法保证在将代码编译成DLL后类仍然不相交。
- 如果没有,是否有办法强制编译器将其转换为查找表?
醇>
如果您始终打开叶子类型,则可以将其转换为类型全名的开关:
switch (c?.GetType().FullName) {
case "MyNamespace.Class1": {
return ParseClass1((MyNamespace.Class1)c);
}
case "MyNamespace.Class2": {
return ParseClass2((MyNamespace.Class2)c);
}
...
}
您可以完全取消开关,将其替换为动态调度:
static IContent ParseContent(dynamic c) => ParseClass(c);
// ^^^^^^^
// This is the part where "magic" takes place
IContent ParseClass(class1 c) {...}
IContent ParseClass(class2 c) {...}
...
IContent ParseClass(class20 c) {...}
IContent ParseClass(object c) => throw new ArgumentException(...);