λ1016: Pass the fallback value directly
A function passed to GetOrElse, OrElse or Match that only returns a plain value should be replaced by the value.
Cause
A lambda is passed to the lazy overload of GetOrElse, OrElse or the none parameter of Match on Option<T>,
Result<T> or Either<L, R>, and its body is nothing but a literal, a constant, a local, a parameter of the enclosing
method, a field or auto-property read on a receiver that cannot be null, typeof or nameof.
Reason for rule
The lazy overload exists to defer work until the fallback is needed. option.GetOrElse(() => 0f) has no work to defer;
the lambda only adds a delegate allocation and noise around the value. The eager overload option.GetOrElse(0f) says
the same thing directly.
A lambda that uses its own parameter (exception => …, left => …) or that does work (a method call, an object
creation, an indexer, a throw) is a legitimate use of the lazy overload and is not reported. Neither are () => null
and () => default, because the bare value would be ambiguous between the two overloads.
How to fix violations
Replace the lambda with its body. A code fix is available.
Examples
Disallowed
static float Example(Option<float> option)
=> option.GetOrElse(() => 0f);
static int Example(Result<int> result, int fallback)
=> result.GetOrElse(_ => fallback);
static Option<int> Example(Option<int> option)
=> option.OrElse(() => Option<int>.None);
Allowed
static float Example(Option<float> option)
=> option.GetOrElse(0f);
static int Example(Result<int> result, int fallback)
=> result.GetOrElse(fallback);
// The function does work that is only needed in the error case.
static Settings Example(Option<Settings> settings)
=> settings.GetOrElse(() => LoadDefaultSettings());
// The function uses the left value.
static int Example(Either<string, int> either)
=> either.GetOrElse(left => left.Length);