Fix MA0075 false positive on Enum.ToString and handle conditional access - #1311
Merged
Conversation
MA0075 reported "Do not use implicit culture-sensitive ToString" for
`"abc" + enumValue.ToString("G")` while MA0185 considered the same value
culture invariant (#1310).
The `ToString` overloads of an enum are declared on `System.Enum`, so the
containing type of the invocation is `System.Enum`, which is a class and
not an enum. It implements `IFormattable`, so it was considered culture
sensitive. `System.Enum` ignores the format provider, so it is now part
of the known culture-insensitive types. This also covers values typed as
`System.Enum` and type parameters constrained to `struct, Enum`.
The false positive only became visible in #1273: before it, the string
concatenation rule only analyzed operands that were implicitly converted
to `object`, so a `string`-typed operand was never analyzed.
`IConditionalAccessOperation` was not handled, so `"abc" +
dateTime?.ToString("F")` was evaluated using the type of the whole
expression (`string`) and never reported. It is now evaluated using the
accessed value.
This was referenced Aug 20, 2026
Closed
Bump Meziantou.Analyzer from 3.0.103 to 3.0.176
Analogy-LogViewer/Analogy.LogViewer.OpenTelemetry#95
Closed
Closed
Closed
Closed
Open
Bump Meziantou.Analyzer from 3.0.139 to 3.0.177
Analogy-LogViewer/Analogy.LogViewer.NLog.Targets#553
Closed
Merged
Closed
This was referenced Aug 27, 2026
Bump Meziantou.Analyzer from 3.0.139 to 3.0.189
Analogy-LogViewer/Analogy.LogViewer.NLog.Targets#556
Open
Open
Bump Meziantou.Analyzer from 3.0.139 to 3.0.189
Analogy-LogViewer/Analogy.AspNetCore.LogProvider#542
Open
Open
Open
Open
Open
Open
Open
Open
Open
Bump Meziantou.Analyzer from 3.0.103 to 3.0.190
Analogy-LogViewer/Analogy.LogViewer.OpenTelemetry#99
Open
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1310
MA0075 vs MA0185 on enums
MA0075 reported
Do not use implicit culture-sensitive ToStringfor"abc" + enumValue.ToString("G"), while MA0185 considered the very same value culture invariant.The
ToStringoverloads of an enum are declared onSystem.Enum, soinvocation.TargetMethod.ContainingTypeisSystem.Enum. That type is a class, soIsEnum()returnsfalse, and it implementsIFormattable, so it was classified as culture sensitive.System.Enumignores the format provider, so it is now part of the known culture-insensitive types.Adding
System.Enumto the type-level check rather than usinginvocation.Instance?.Typealso covers values statically typed asSystem.Enumand type parameters constrained towhere T : struct, Enum.Note that the underlying gap is not new: it only became visible in #1273, which changed the string concatenation rule from analyzing only operands implicitly converted to
objectto analyzing every operand. Before that, astring-typed operand such asenumValue.ToString("G")was never analyzed at all.Conditional access
Found while investigating the above:
IConditionalAccessOperationwas not handled, so it fell through to the generic branch that uses the type of the whole expression. For"abc" + dateTime?.ToString("F")that type isstring, so the rule never reported it. The culture sensitivity is now computed fromWhenNotNull.This only affects MA0075/MA0076. MA0185 reaches interpolation holes through
IInterpolatedStringAppendOperation, which works off argument types, so its behavior is unchanged.Tests
G g F f D d X x,default(string), a non-constantstring format), plainToString(), implicit concat, nullable enums,System.Enum-typed values, user-defined enums,where T : struct, Enum, and the interpolated-string forms.value?.ToString(),value?.ToString("F"),value?.ToString(format),value?.Date.ToString("F"),value?.Ticks.ToString(), nestedvalue?.Child?.Value.ToString("F"),value?.Value, and the interpolated form are reported;value?.ToString("o"),value?.ToString(CultureInfo.InvariantCulture),value?.Ticks.ToString("X")andvalue?.Kind.ToString("G")are not."abc" + value?.Ticks.ToString()is reported on purpose:Ticksis a non-constantlong, and MA0075 already treats non-constant signed integers as culture sensitive because of the negative sign.Note for the reviewer
Enum.ToString("D")on an undefined value of a signed enum formats the underlying integer with the current culture, so a negative value picks up the culture's negative sign. TreatingSystem.Enumas unconditionally invariant ignores that. This is consistent with what MA0075 already did for"abc" + enumValueand with MA0185, but it is not literally always invariant.Validation
dotnet test --max-parallel-test-modules 2: 18327 passed, 0 failed (all five Roslyn versions)dotnet run --project src/DocumentationGenerator: exit code 0, no generated markdown change