为何在switch常量case中调用ToLower()会触发CS0426等编译错误?
咱们先把核心规则摆出来:C#的switch语句中,case标签必须是编译期可确定的常量表达式,你遇到的所有错误都是围绕这个规则衍生出来的,下面逐个拆解:
1. 第二个switch的CS0426错误:类型名称'A'不存在
你写的case ClassificationIdentifiers.ClassificationIdentifiersChildren.A.ToLower():看似是对常量字符串调用ToLower(),但编译器根本不允许在case标签的常量表达式里调用实例方法。
这里的错误提示有点误导人——编译器在解析这个表达式时,因为它要求case标签是纯常量,而ToLower()是需要运行时执行的实例方法(不属于编译期可计算的常量操作),所以它错误地将ClassificationIdentifiers.ClassificationIdentifiersChildren.A解析为类型访问(而非常量字符串成员),试图寻找名为A的嵌套类型,再访问该类型的ToLower()方法。但你的代码里A是const字符串不是类型,于是就报出了“类型名称'A'不存在”的错误。
本质原因:case标签的表达式必须是编译期就能确定结果的常量,调用实例方法(哪怕是对常量字符串调用)不符合这个要求,编译器的解析逻辑在这里出现了偏差,给出了看似无关的错误提示,但根源是违反了switch case的常量规则。
2. const赋值的CS0133错误:表达式必须是常量
const string a = "A".ToLower();触发这个错误的原因很直接:const字段/变量要求初始化值是编译期就能确定的常量,而string.ToLower()是一个运行时执行的方法——它的结果理论上依赖于运行时的文化设置(哪怕这里看起来结果固定,编译器也不会做这种假设),属于运行时计算的表达式,所以不能用来初始化const变量。
如果你想实现类似效果,可以改用readonly:
readonly string a = "A".ToLower();
不过readonly是运行时初始化,依然不能用在switch的case标签里。
3. case中使用a.ToLower()的CS0118错误:变量被当作类型使用
同样是因为case标签要求常量表达式,a如果是普通变量(哪怕是readonly),a.ToLower()是变量的实例方法调用,属于运行时计算的值,不符合常量要求。
编译器在这里的错误提示是因为它在期望常量的位置看到了变量.方法()的写法,错误地将a解析为类型(试图访问类型a的ToLower()成员),所以报出“'a'是变量,但被当作类型使用”的错误——本质还是违反了case标签必须是常量的规则。
正确的替代方案
如果你需要匹配小写的字符串值,有两种常见做法:
- 在switch之前先把输入值转成小写,然后匹配常量的小写版本:
var lowerCaseType = classificationFileType.ToLower(); switch (lowerCaseType) { case "a": // 直接用小写常量字符串 classification = ClassificationIdentifiers.ClassificationIdentifiersChildren.A; break; } - 或者使用C# 7.0+的模式匹配,配合when子句(这种方式不要求case是常量,但性能略逊于普通switch):
switch (classificationFileType) { case var s when s.ToLower() == ClassificationIdentifiers.ClassificationIdentifiersChildren.A.ToLower(): classification = ClassificationIdentifiers.ClassificationIdentifiersChildren.A; break; }
内容的提问来源于stack exchange,提问作者Ogglas

