I am using string comparisons to test URL paths using StringComparison.OrdinalIgnoreCase.
MSDN gives the following string comparison advice HERE, but does not clarify WHY:
MSDN Example (half-way down the above page):
public static bool IsFileURI(string path)
{
path.StartsWith("FILE:", StringComparison.OrdinalIgnoreCase);
return true;
}
MSDN Advice:
“However, the preceding example uses the String.StartsWith(String, StringComparison) method to test for equality. Because the purpose of the comparison is to test for equality instead of ordering the strings, a better alternative is to call the Equals method, as shown in the following example.”
public static bool IsFileURI(string path)
{
if (path.Length < 5) return false;
return String.Equals(path.Substring(0, 5), "FILE:",
StringComparison.OrdinalIgnoreCase);
}
QUESTION: Why does MSDN suggest the second example is better?
Discussion points:
-
Clearly the
return true;in the first example is a bug and should bereturn path.StartsWith(...);. We can safely ignore this as a bug as the VB code is correct. -
Creation of a substring prior to comparing for equality would appear to only use another memory resource than just calling String.StartsWith().
-
The Length < 5 test is a nice short-circuit, however it could be used with the prior code just the same.
-
The second example could be construed as clearer code, but I am concerned with performance. The creation of the substring seems unnecessary.
Looking at the
StartsWithmethod using dotPeek, it eventually calls an internal comparison function that compares the entire string, and returns a boolean result based on the return value of that comparison:String.Equalscalls:CompareOrdinalIgnoreCasecalls a private method, which dotPeek doesn’t show, but my hunch is that the overload called byStartsWithtraverses the entire string while the overload called byEqualsstops as soon as equality can be determined.If performance is a concern, try measuring both with values that will be typical for your application.
Out of curiousity, I tried measuring the two, and it does seem that
Equalsis noticeably faster. When I run the code below using a release build,Equalsis nearly twice as fast asStartsWith: