C#中如何用switch或字典实现含特定字符串的文件名映射ID?
解决C#中多条件文件名匹配的简洁方案
嗨,作为C#新手,你这个需求太典型了——用一堆if确实会让代码臃肿又难维护,换成switch或者字典完全可行,而且能让代码清爽很多。先给你指出原来写法里的小问题:string.Contains(fileName)的语法不对,而且匹配顺序是核心,更具体的规则必须放在前面,不然会被宽泛的规则抢先命中(比如如果先判断.xml,那_MAP_COPY.xml的文件永远只会返回3300而不是3310)。
下面给你两种靠谱的实现方式:
方案一:用C#模式匹配的Switch表达式(推荐)
从C# 8.0开始支持的switch表达式非常适合这种场景,写法简洁还能清晰控制优先级:
private int GetFileTypeId(string fileName) { return fileName switch { // 优先级从高到低:最具体的匹配放在最前面 var name when name.Contains("_MAP_COPY.xml") => 3310, var name when name.Contains("_Gui.xml") => 3120, var name when name.Contains(".xsd") => 3010, var name when name.Contains(".xml") => 3300, // 在这里继续添加剩下的14个匹配规则,记得保持优先级顺序 // 如果没有匹配项,抛出异常或者返回默认值,根据你的业务需求调整 _ => throw new ArgumentException($"无法识别文件类型:{fileName}", nameof(fileName)) }; }
为什么推荐这个?
- 语法紧凑,比一堆if可读性高太多
- 能直观控制匹配优先级,按从上到下的顺序判断
- 如果以后要修改规则,直接调整顺序或者添加case就行
方案二:用有序规则列表+字典思想(适合大量规则)
如果你的18个规则以后可能经常变动,用有序列表来维护会更灵活,本质是把匹配规则和ID绑定,然后按优先级遍历匹配:
// 定义一个静态的有序规则列表,顺序就是匹配优先级(越靠前优先级越高) private static readonly List<(string MatchPattern, int FileTypeId)> _fileTypeRules = new() { ("_MAP_COPY.xml", 3310), ("_Gui.xml", 3120), (".xsd", 3010), (".xml", 3300), // 把剩下的14个规则按优先级依次添加进来 }; private int GetFileTypeId(string fileName) { // 找到第一个匹配的规则 var matchedRule = _fileTypeRules.FirstOrDefault(rule => fileName.Contains(rule.MatchPattern)); if (matchedRule != default) { return matchedRule.FileTypeId; } // 没有匹配到的情况,自行处理 throw new ArgumentException($"无法识别文件类型:{fileName}", nameof(fileName)); }
这个方案的优势:
- 规则集中管理,新增/删除/调整优先级只需要修改列表,不用动方法逻辑
- 当规则数量很多(比如你的18个),列表的可读性比长switch更好
额外注意点
- 大小写问题:如果需要忽略文件名的大小写,可以在
Contains方法里加参数,比如name.Contains("_MAP_COPY.xml", StringComparison.OrdinalIgnoreCase),避免因为文件名大小写不一致导致匹配失败。 - 默认情况处理:一定要考虑没有匹配到任何规则的场景,要么抛出明确的异常,要么返回一个默认的ID(比如0),根据你的业务逻辑来决定。
内容的提问来源于stack exchange,提问作者Emil Carlsson
相关产品推荐
相关产品推荐

