Case insensitive ‘Contains(string)’
技术背景
在软件开发中,经常需要判断一个字符串是否包含另一个字符串,并且有时需要忽略大小写进行匹配。例如,在搜索功能中,用户输入的关键词可能大小写与目标字符串不一致,但我们仍希望能正确匹配。
实现步骤
1. 使用 String.IndexOf 方法
可以使用 String.IndexOf 方法并传入 StringComparison.OrdinalIgnoreCase 作为搜索类型:
1 2
| string title = "STRING"; bool contains = title.IndexOf("string", StringComparison.OrdinalIgnoreCase) >= 0;
|
2. 定义扩展方法
为字符串定义一个新的扩展方法:
1 2 3 4 5 6 7
| public static class StringExtensions { public static bool Contains(this string source, string toCheck, StringComparison comp) { return source?.IndexOf(toCheck, comp) >= 0; } }
|
注意,?. 是 C# 6.0(VS 2015)引入的空传播运算符,对于旧版本可以使用:
1 2
| if (source == null) return false; return source.IndexOf(toCheck, comp) >= 0;
|
使用示例:
1 2
| string title = "STRING"; bool contains = title.Contains("string", StringComparison.OrdinalIgnoreCase);
|
3. 使用 CultureInfo.CompareInfo.IndexOf
要测试字符串 paragraph 是否包含字符串 word,可以使用:
1
| culture.CompareInfo.IndexOf(paragraph, word, CompareOptions.IgnoreCase) >= 0
|
其中 culture 是 CultureInfo 的实例,描述文本所使用的语言。
4. .NET Core 2.0+
.NET Core 2.0 及以上版本提供了两个方法来处理此问题:
String.Contains(Char, StringComparison)String.Contains(String, StringComparison)
示例:
1
| "Test".Contains("test", System.StringComparison.CurrentCultureIgnoreCase);
|
5. 使用正则表达式
1
| bool contains = Regex.IsMatch("StRiNG to search", Regex.Escape("string"), RegexOptions.IgnoreCase);
|
6. 先转换大小写
1 2
| string title = "string"; title.ToUpper().Contains("STRING");
|
7. 使用 InStr 方法
在 VB.NET 中已经有这样的函数,C# 可以使用 Microsoft.VisualBasic.Strings.InStr 方法:
1 2
| string myString = "Hello World"; bool contains = Microsoft.VisualBasic.Strings.InStr(myString, "world");
|
8. 使用 string.Compare 方法
1
| string.Compare("string", "STRING", new System.Globalization.CultureInfo("en-US"), System.Globalization.CompareOptions.IgnoreCase);
|
9. 自定义扩展方法
1 2 3 4
| public static bool ContainsIgnoreCase(this string paragraph, string word) { return CultureInfo.CurrentCulture.CompareInfo.IndexOf(paragraph, word, CompareOptions.IgnoreCase) >= 0; }
|
10. 简化扩展方法
1 2 3 4 5 6 7
| public static class StringExtensions { public static bool Contains(this string source, string toCheck, bool bCaseInsensitive ) { return source.IndexOf(toCheck, bCaseInsensitive ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal) >= 0; } }
|
使用示例:
1 2 3 4
| if( "main String substring".Contains("SUBSTRING", true) ) { }
|
11. 简单的检查方法
1 2 3
| string yourStringForCheck = "abc"; string stringInWhichWeCheck = "Test abc abc"; bool isContained = stringInWhichWeCheck.ToLower().IndexOf(yourStringForCheck.ToLower()) > -1;
|
12. 带空检查的扩展方法
1 2 3 4
| public static bool ContainsIgnoreCase(this string source, string substring) { return source?.IndexOf(substring ?? "", StringComparison.OrdinalIgnoreCase) >= 0; }
|
最佳实践
- 对于不涉及特定文化的字符串匹配,建议使用
StringComparison.OrdinalIgnoreCase 作为默认选项,因为它速度更快。 - 当需要向用户显示输出时,使用基于
StringComparison.CurrentCulture 的字符串操作。 - 在比较与语言无关的符号时,将当前基于不变文化的字符串操作切换为使用非语言的
StringComparison.Ordinal 或 StringComparison.OrdinalIgnoreCase。 - 规范化字符串进行比较时,使用
ToUpperInvariant 而不是 ToLowerInvariant。
常见问题
- 空字符串问题:如果字符串为 null,某些方法可能会抛出异常。可以在方法中添加空检查来避免这种情况,如在扩展方法中添加
if (string.IsNullOrEmpty(toCheck) || string.IsNullOrEmpty(source)) return true;。 - 文化差异问题:不同语言对大小写的定义可能不同,如英语和土耳其语。在进行大小写不敏感比较时,需要考虑文本所使用的语言。如果不知道语言,可以使用
CultureInfo.InvariantCulture。