λ1201: Prefer the static ParseOrNone member on the parsed type
Since 3.8.0 every Parse…OrNone extension on string and on spans also exists as a static extension member on the type
it parses. text.ParseInt32OrNone() is int.ParseOrNone(text), which reads like the int.TryParse it wraps.
Cause
A Parse…OrNone extension of ParseExtensions is called on a string, a ReadOnlySpan<char> or a ReadOnlySpan<byte>,
the file is compiled as C# 14 or later, and the static member on the parsed type binds for the same arguments. The rule
covers the generated members (ParseInt32OrNone, ParseExactDateTimeOrNone, …), the enum form
(ParseEnumOrNone<TEnum>) and the generic forms (ParseOrNone<T>, ParseNumberOrNone<T>); the parsed type comes
from the Option<T> the extension returns.
A method group (texts.Select(ParseExtensions.ParseInt32OrNone)) is not reported: a static extension member has no
method-group form of the same shape.
Reason for rule
The static form is the one that mirrors the base class library, and it is the form that survives if 4.0.0 retires the
string family. Adopting it in one sweep is what the code fix is for.
How to fix violations
Call the static member on the parsed type with the text as the first argument. The code fix does this, keeps the other arguments and their names, and supports fix-all.
Examples
Disallowed
Option<int> number = text.ParseInt32OrNone();
Option<DateTime> date = text.ParseExactDateTimeOrNone("O", CultureInfo.InvariantCulture);
Option<Color> color = text.ParseEnumOrNone<Color>(ignoreCase: true);
Allowed
Option<int> number = int.ParseOrNone(text);
Option<DateTime> date = DateTime.ParseExactOrNone(text, "O", CultureInfo.InvariantCulture);
Option<Color> color = Color.ParseOrNone(text, ignoreCase: true);
// A method group has no static counterpart of the same shape.
IEnumerable<Option<int>> numbers = texts.Select(ParseExtensions.ParseInt32OrNone);