diff --git a/strings-csharp/CaseInsensitiveSubstringSearch/BenchmarkRunner/BenchmarkRunner.csproj b/strings-csharp/CaseInsensitiveSubstringSearch/BenchmarkRunner/BenchmarkRunner.csproj
index 083757afe1..46ec814a74 100644
--- a/strings-csharp/CaseInsensitiveSubstringSearch/BenchmarkRunner/BenchmarkRunner.csproj
+++ b/strings-csharp/CaseInsensitiveSubstringSearch/BenchmarkRunner/BenchmarkRunner.csproj
@@ -2,13 +2,13 @@
Exe
- net7.0
+ net10.0
enable
enable
-
+
diff --git a/strings-csharp/CaseInsensitiveSubstringSearch/CaseInsensitiveSubstringSearch/CaseInsensitiveSubstringSearch.csproj b/strings-csharp/CaseInsensitiveSubstringSearch/CaseInsensitiveSubstringSearch/CaseInsensitiveSubstringSearch.csproj
index f02677bf64..dfb40caafc 100644
--- a/strings-csharp/CaseInsensitiveSubstringSearch/CaseInsensitiveSubstringSearch/CaseInsensitiveSubstringSearch.csproj
+++ b/strings-csharp/CaseInsensitiveSubstringSearch/CaseInsensitiveSubstringSearch/CaseInsensitiveSubstringSearch.csproj
@@ -2,7 +2,7 @@
Exe
- net7.0
+ net10.0
enable
enable
diff --git a/strings-csharp/CaseInsensitiveSubstringSearch/CaseInsensitiveSubstringSearch/SubstringSearch.cs b/strings-csharp/CaseInsensitiveSubstringSearch/CaseInsensitiveSubstringSearch/SubstringSearch.cs
index db8b1143a9..cda2b1cd08 100644
--- a/strings-csharp/CaseInsensitiveSubstringSearch/CaseInsensitiveSubstringSearch/SubstringSearch.cs
+++ b/strings-csharp/CaseInsensitiveSubstringSearch/CaseInsensitiveSubstringSearch/SubstringSearch.cs
@@ -28,13 +28,20 @@ public static bool StringToUpperInvariant(string sourceString, string substringT
}
// Regular Expression Search
+ // Regex.Escape() treats the search term as literal text, so a term such as "c.de" or "z*"
+ // is not reinterpreted as a pattern and an unmatched bracket does not throw.
+ // RegexOptions.CultureInvariant keeps IgnoreCase off the current culture's casing rules.
public static bool RegexIsMatch(string sourceString, string substringToSearch)
{
return Regex
- .IsMatch(sourceString, substringToSearch, RegexOptions.IgnoreCase);
+ .IsMatch(sourceString,
+ Regex.Escape(substringToSearch),
+ RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
}
// Linq With String Equals Method Search
+ // This matches whole separator-delimited words, not substrings, so it answers a different
+ // question from the other four methods. That difference is intentional, not a bug.
public static bool LinqStringEquals(string sourceString, string substringToSearch, char separator)
{
return sourceString
diff --git a/strings-csharp/CaseInsensitiveSubstringSearch/Tests/SubstringSearchSemanticsTest.cs b/strings-csharp/CaseInsensitiveSubstringSearch/Tests/SubstringSearchSemanticsTest.cs
new file mode 100644
index 0000000000..92daa4363a
--- /dev/null
+++ b/strings-csharp/CaseInsensitiveSubstringSearch/Tests/SubstringSearchSemanticsTest.cs
@@ -0,0 +1,60 @@
+using System.Globalization;
+using CaseInsensitiveSubstringSearch;
+
+namespace Tests
+{
+ [TestClass]
+ public class SubstringSearchSemanticsTest
+ {
+ private const string SourceString = "Code Maze";
+
+ [TestMethod]
+ [DataRow("aze")]
+ [DataRow("ode")]
+ [DataRow("e M")]
+ public void GivenMidWordSubstring_WhenComparingAllFiveMethods_ThenOnlyLinqStringEqualsReturnsFalse(string subStringToSearch)
+ {
+ Assert.IsTrue(SubstringSearch.StringContains(SourceString, subStringToSearch));
+ Assert.IsTrue(SubstringSearch.StringIndexOf(SourceString, subStringToSearch));
+ Assert.IsTrue(SubstringSearch.StringToUpperInvariant(SourceString, subStringToSearch));
+ Assert.IsTrue(SubstringSearch.RegexIsMatch(SourceString, subStringToSearch));
+
+ Assert.IsFalse(SubstringSearch.LinqStringEquals(SourceString, subStringToSearch, ' '));
+ }
+
+ [TestMethod]
+ [DataRow("c.de")]
+ [DataRow("z*")]
+ [DataRow("m|q")]
+ [DataRow("(")]
+ public void GivenSearchTermHoldingRegexMetacharacters_WhenUsingRegexIsMatchMethod_ThenItAgreesWithStringContains(string subStringToSearch)
+ {
+ var expectedResult = SubstringSearch.StringContains(SourceString, subStringToSearch);
+
+ var result = SubstringSearch.RegexIsMatch(SourceString, subStringToSearch);
+
+ Assert.AreEqual(expectedResult, result);
+ Assert.IsFalse(result);
+ }
+
+ [TestMethod]
+ public void GivenTurkishCulture_WhenSearchingForFileInsideFILE_ThenAllFourContainmentMethodsMatch()
+ {
+ var originalCulture = CultureInfo.CurrentCulture;
+
+ try
+ {
+ CultureInfo.CurrentCulture = new CultureInfo("tr-TR");
+
+ Assert.IsTrue(SubstringSearch.StringContains("FILE", "file"));
+ Assert.IsTrue(SubstringSearch.StringIndexOf("FILE", "file"));
+ Assert.IsTrue(SubstringSearch.StringToUpperInvariant("FILE", "file"));
+ Assert.IsTrue(SubstringSearch.RegexIsMatch("FILE", "file"));
+ }
+ finally
+ {
+ CultureInfo.CurrentCulture = originalCulture;
+ }
+ }
+ }
+}
diff --git a/strings-csharp/CaseInsensitiveSubstringSearch/Tests/Tests.csproj b/strings-csharp/CaseInsensitiveSubstringSearch/Tests/Tests.csproj
index fbf6af0b48..a75aead610 100644
--- a/strings-csharp/CaseInsensitiveSubstringSearch/Tests/Tests.csproj
+++ b/strings-csharp/CaseInsensitiveSubstringSearch/Tests/Tests.csproj
@@ -1,7 +1,7 @@
- net7.0
+ net10.0
enable
enable
@@ -9,10 +9,10 @@
-
-
-
-
+
+
+
+