You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VB Like运算符相邻通配符异常行为及跨平台实现差异疑问

VB LikeOperator 行为差异与.NET Standard 2.0替代方案

问题背景

我在C#中使用Microsoft.VisualBasic.CompilerServices.LikeOperator,现在要迁移到不支持该类的.NET Standard 2.0。测试时发现一个异常行为:模式"foo*?bar"本应匹配以"foo"开头、"bar"结尾且中间至少有一个字符的字符串,但.NET Framework里调用LikeOperator.LikeString("foobar", "foo*?bar", CompareMethod.Text)居然返回true。而Mono 6.12.0的VB.NET实现中,这个模式正确拒绝了"foobar",显然是.NET Framework的实现存在bug。

问题原因

这是.NET Framework对LikeOperator的实现缺陷:*匹配任意数量字符(包括0个),?要求匹配单个字符,但当*和?相邻时,.NET Framework错误地让*的0长度匹配覆盖了?的单个字符要求,导致中间没有字符的"foobar"被误判为匹配。

适配.NET Standard 2.0的解决方案

既然.NET Standard 2.0不支持LikeOperator,我们可以把VB Like模式转换成等效的正则表达式,同时修正这个bug的影响:

1. 基础模式转换规则

把VB Like的通配符映射到正则:

  • * → .*(匹配任意长度字符,包括0)
  • ? → .(匹配单个任意字符)
  • 先转义正则中的特殊字符(比如., +, *这些),避免语法冲突

2. 针对*?的特殊修正

原模式foo*?bar要求中间至少一个字符,对应的正则不能直接用^foo.*.bar$(这会复现.NET Framework的错误逻辑),而是要确保中间至少有一个字符,所以应该用^foo.+bar$(.+匹配至少一个任意字符)。

3. 代码示例

using System.Text.RegularExpressions;

bool VbLikeMatch(string input, string likePattern)
{
    // 先转义正则特殊字符,再替换VB通配符
    string regexPattern = "^" + Regex.Escape(likePattern)
                                    .Replace(@"\*", ".*")
                                    .Replace(@"\?", ".") + "$";
    
    // 修正.NET Framework的*? bug:把.*.替换成.+,确保中间至少一个字符
    regexPattern = regexPattern.Replace(@".*\.", ".+");
    
    // 对应CompareMethod.Text的忽略大小写规则
    return Regex.IsMatch(input, regexPattern, RegexOptions.IgnoreCase);
}

// 测试验证
bool testResult1 = VbLikeMatch("foobar", "foo*?bar"); // 返回false,符合预期
bool testResult2 = VbLikeMatch("fooxbar", "foo*?bar"); // 返回true,符合预期
bool testResult3 = VbLikeMatch("fooxyzbar", "foo*?bar"); // 返回true,符合预期

4. 扩展注意事项

如果你的模式里还有VB Like特有的语法,比如字符列表[a-z]、排除列表[!0-9],需要额外处理这些规则:

  • [abc] → 直接保留为[abc](正则兼容该语法)
  • [!abc] → 转换为[^abc](正则的排除语法)
  • 范围匹配[a-z]直接保留即可

内容的提问来源于stack exchange,提问作者Wim Coenen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 10:15:27