Normalize Strings
ID |
csharp.normalize_strings |
Severity |
low |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
CSharp |
Tags |
culture, reliability, string |
Description
Reports ToLowerInvariant() and ToUpperInvariant() calls on string receivers.
These methods sound culture-safe but still apply Unicode casing transforms that produce
surprises with the Turkish dotted-i family and a few other characters.
Rationale
When two strings need to be compared case-insensitively the .NET-recommended pattern is
to call String.Equals(other, StringComparison.OrdinalIgnoreCase) directly. Casing the
string and then comparing materialises an extra allocation and can still misbehave for
characters whose invariant casing is not idempotent.
public class Norm
{
public bool MatchUpper(string a, string b)
{
return a.ToUpperInvariant() == b.ToUpperInvariant(); // FLAW (twice)
}
public bool MatchLower(string a, string b)
{
return a.ToLowerInvariant().Equals(b); // FLAW
}
public bool MatchOrdinal(string a, string b)
{
return a.Equals(b, StringComparison.OrdinalIgnoreCase); // OK
}
}
Remediation
Replace a.ToLowerInvariant() == b.ToLowerInvariant() with
String.Equals(a, b, StringComparison.OrdinalIgnoreCase). When a normalized form is
genuinely required (Unicode normalization for storage), call
Normalize(NormalizationForm.FormC) followed by casing under
CultureInfo.InvariantCulture.