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
。