-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Analyzer] Recommend string.ToLower{Invariant}().Contains/IndexOf/StartsWith("lowercasestring") be replaced by case-insensitive comparison #78606
Comments
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label. |
|
Tagging subscribers to this area: @dotnet/area-system-runtime Issue DetailsThere's a significant amount of code that's apparently trying to perform case-insensitive comparisons by first lower-casing and then comparing against a lowercased string, e.g. We should write an analyzer that flags these patterns and recommends comparisons using a StringComparer instead.
|
Tagging subscribers to this area: @dotnet/area-system-globalization Issue DetailsThere's a significant amount of code that's apparently trying to perform case-insensitive comparisons by first lower-casing and then comparing against a lowercased string, e.g. We should write an analyzer that flags these patterns and recommends comparisons using a StringComparer instead. Such analyzers will help avoid the allocations caused by ToLower/ToUpper calls. Performance rules Category
|
CC @Youssef1313 |
Looks good as proposed. All of these cases should ideally use the same diagnostic ID, but if the implementation of the fixer necessitates multiple then that is what it is. In addition to a.ToLower().Contains(...), it should also identify a.Contains(b.ToLower()) (et al) It further includes a.CompareTo(b.ToLower{Invariant}()) becoming StringComparer.{Invariant}IgnoreCase.Compare(a, b). Category:Performance |
I'll work on this. Question: Should we always recommend the same Adding a quick table for myself, for easier reference:
|
@carlossanlop |
Thank @tarekgh. Another question: For the
The |
This analyzer approval did not include the ToUpper/ToLower overloads that takes culture info. But it is possible we can include these cases too. Can use On a separate note, there is a comment at #78606 (comment) containing instructions that we should carefully consider, in case you haven't already reviewed it. CC @stephentoub |
Yep. I included them in my table. And you're right, they were not mentioned in the approval. By default I will ignore the CultureInfo overloads, considering they would add much more complexity to the analyzer. I'll only address them if told to do so. |
@tarekgh The using System;
string a = "a";
string b = "A";
Console.WriteLine(a.ToLower().CompareTo(b)); // -1
Console.WriteLine(StringComparer.CurrentCultureIgnoreCase.Compare(a, b)); // 0
Console.WriteLine(a.ToLowerInvariant().CompareTo(b)); // -1
Console.WriteLine(StringComparer.InvariantCultureIgnoreCase.Compare(a, b)); // 0 Do we need to change the way the fix behaves for this case? Or should we skip this diagnose altogether? |
Usually, users who are doing something like @stephentoub what do you think about this case? |
Should we consider also detecting simple patterns across statements, such as below? var loweredStr = str.ToLower();
if (loweredStr.Contains(anotherStr)) We would need to check that we have exactly one reference to the intermediate temporary variable. If yes, we already added another analyzer which implements a simple heuristic for detecting above patterns: https://github.com/dotnet/roslyn-analyzers/blob/main/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Runtime/PreferStringContainsOverIndexOfAnalyzer.cs. If not for v1, but feel it may be a worthwhile enhancement, you may also consider filing a tracking issue for this enhancement. |
There's a significant amount of code that's apparently trying to perform case-insensitive comparisons by first lower-casing and then comparing against a lowercased string, e.g.
https://grep.app/search?q=.ToLower%28%29.Contains&filter[lang][0]=C%23
https://grep.app/search?q=.ToLower%28%29.IndexOf&filter[lang][0]=C%23
https://grep.app/search?q=.ToLower%28%29.StartsWith&filter[lang][0]=C%23
Less but still many for ToUpper with upper-case, e.g.
https://grep.app/search?q=.ToUpper%28%29.Contains&filter[lang][0]=C%23
https://grep.app/search?q=.ToUpper%28%29.IndexOf&filter[lang][0]=C%23
https://grep.app/search?q=.ToUpper%28%29.StartsWith&filter[lang][0]=C%23
and with the Invariant variations, e.g.
https://grep.app/search?q=.ToLowerInvariant%28%29.Contains&filter[lang][0]=C%23
We should write an analyzer that flags these patterns and recommends comparisons using a
StringComparison
instead.Such analyzers will help avoid the allocations caused by ToLower/ToUpper calls.
Performance rules Category
Severity = suggestion
The text was updated successfully, but these errors were encountered: