I do not pretend to be an expert in this field, but I was forced to at least profile it to some extent (knowing that my dummy scenario will be significantly different from your own), and here is what I came up with:
It seems, at least for me, EndsWith is leading with LastIndexOf , sequentially entering the second, some timings:
SubString: 00:00:00.0191877 Contains: 00:00:00.0201980 CompareInfo: 00:00:00.0255181 EndsWith: 00:00:00.0120296 LastIndexOf: 00:00:00.0133181
They were gleaned from processing 100,000 lines, where the desired suffix appeared in all lines, and therefore, for me, just echoes of John's answer (where the advantage is speed and descriptiveness). And the code used to achieve these results:
class Program { class Profiler { private Stopwatch Stopwatch = new Stopwatch(); public TimeSpan Elapsed { get { return Stopwatch.Elapsed; } } public void Start() { Reset(); Stopwatch.Start(); } public void Stop() { Stopwatch.Stop(); } public void Reset() { Stopwatch.Reset(); } } static string suffix = "_sfx"; static Profiler profiler = new Profiler(); static List<string> input = new List<string>(); static List<string> output = new List<string>(); static void Main(string[] args) { GenerateSuffixedStrings(); FindStringsWithSuffix_UsingSubString(input, suffix); Console.WriteLine("SubString: {0}", profiler.Elapsed); FindStringsWithSuffix_UsingContains(input, suffix); Console.WriteLine("Contains: {0}", profiler.Elapsed); FindStringsWithSuffix_UsingCompareInfo(input, suffix); Console.WriteLine("CompareInfo: {0}", profiler.Elapsed); FindStringsWithSuffix_UsingEndsWith(input, suffix); Console.WriteLine("EndsWith: {0}", profiler.Elapsed); FindStringsWithSuffix_UsingLastIndexOf(input, suffix); Console.WriteLine("LastIndexOf: {0}", profiler.Elapsed); Console.WriteLine(); Console.WriteLine("Press any key to exit..."); Console.ReadKey(); } static void GenerateSuffixedStrings() { for (var i = 0; i < 100000; i++) { input.Add(Guid.NewGuid().ToString() + suffix); } } static void FindStringsWithSuffix_UsingSubString(IEnumerable<string> strings, string suffix) { output.Clear(); profiler.Start(); foreach (var s in strings) { if(s.Substring(s.Length - 4) == suffix) output.Add(s); } profiler.Stop(); } static void FindStringsWithSuffix_UsingContains(IEnumerable<string> strings, string suffix) { output.Clear(); profiler.Start(); foreach (var s in strings) { if (s.Contains(suffix)) output.Add(s); } profiler.Stop(); } static void FindStringsWithSuffix_UsingCompareInfo(IEnumerable<string> strings, string suffix) { var ci = CompareInfo.GetCompareInfo("en-GB"); output.Clear(); profiler.Start(); foreach (var s in strings) { if (ci.IsSuffix(s, suffix)) output.Add(s); } profiler.Stop(); } static void FindStringsWithSuffix_UsingEndsWith(IEnumerable<string> strings, string suffix) { output.Clear(); profiler.Start(); foreach (var s in strings) { if (s.EndsWith(suffix)) output.Add(s); } profiler.Stop(); } static void FindStringsWithSuffix_UsingLastIndexOf(IEnumerable<string> strings, string suffix) { output.Clear(); profiler.Start(); foreach (var s in strings) { if (s.LastIndexOf(suffix) == s.Length - 4) output.Add(s); } profiler.Stop(); } }
EDIT:
As commented, I tried to repeat this with only some lines having a suffix, and these are the results:
SubString: 00:00:00.0079731 Contains: 00:00:00.0243696 CompareInfo: 00:00:00.0334056 EndsWith: 00:00:00.0196668 LastIndexOf: 00:00:00.0229599
The line generator method has been updated as follows to create lines:
static void GenerateSuffixedStrings() { var nxt = false; var rnd = new Random(); for (var i = 0; i < 100000; i++) { input.Add(Guid.NewGuid().ToString() + (rnd.Next(0, 2) == 0 ? suffix : string.Empty)); } }
Further, this trend continues if none of the lines has a suffix:
SubString: 00:00:00.0055584 Contains: 00:00:00.0187089 CompareInfo: 00:00:00.0228983 EndsWith: 00:00:00.0114227 LastIndexOf: 00:00:00.0199328
However, this gap is narrowed by assigning a quarter of the suffix entries (first quarter and then sorting to randomise coverage):
SubString: 00:00:00.0302997 Contains: 00:00:00.0305685 CompareInfo: 00:00:00.0306335 EndsWith: 00:00:00.0351229 LastIndexOf: 00:00:00.0322899
Output? IMO, and agreeing with John, EndsWith seems to be the way to go (based on this limited test, anyway).
Further editing:
To cure John's curiosity, I did some more tests on EndsWith , with and without Ordinal string comparison ...
In 100,000 lines with a quarter of suffixes:
EndsWith: 00:00:00.0795617 OrdinalEndsWith: 00:00:00.0240631
For 1,000,000 lines with a quarter of suffixes:
EndsWith: 00:00:00.5460591 OrdinalEndsWith: 00:00:00.2807860
In 10,000,000 lines with a quarter of suffixes:
EndsWith: 00:00:07.5889581 OrdinalEndsWith: 00:00:03.3248628
Please note that I only ran the last test once, creating lines proving that this laptop needs to be replaced