I have almost successfully updated an library of mine to be "nullable aware". However the following code gives me trouble.
public static Result<string, TValid> ResultMustBe<TValid>
(
this TValid self,
params Func<TValid, Result<string, TValid>>[] validators
)
{
var caller = new StackFrame(1)?.GetMethod()?.DeclaringType?.FullName ?? "?";
if (!validators.Any())
{
throw new ArgumentException($"No validators provided for EitherMustBe in {caller}");
}
Result<string, TValid>? result = null;
foreach (var validator in validators)
{
try
{
result = validator(self);
if (result is Result<string, TValid>.Invalid left)
{
return Result<string, TValid>.MakeInvalid(left.Error.Replace("<<caller>>", caller));
}
}
catch (Exception ex)
{
throw new ValidationException($"Uncaught exception occured while validating {caller}", ex);
}
}
// Warning produced here
return result! as Result<string, TValid>.Valid;
}
public abstract class Result<TInvalid, TValid>
{
public static Valid MakeValid(TValid data)
{
return new Valid(data);
}
public static Invalid MakeInvalid(TInvalid error)
{
return new Invalid(error);
}
public abstract bool IsValid { get; }
public class Invalid : Result<TInvalid, TValid>
{
public TInvalid Error { get; }
public override bool IsValid => false;
public Invalid(TInvalid error)
{
Error = error;
}
}
public class Valid : Result<TInvalid, TValid>
{
public TValid Data { get; }
public override bool IsValid => true;
public Valid(TValid data)
{
Data = data;
}
}
}
The compiler gives me a warning for the return with [CS8603] Possible null reference return which I sort of can understand, seeing as I initialize result with null. However the method can never actually return null, result will always be the latest returned value from validator.
Is a pragma warning diable my only option here, or am I missing something? I should add that I don't want to change the return type of my method Either (as again, it should be null-safe).
Edit: Renamed the class Either to Result (return type) as it distracted away from the question. Also included the code for the class. As asked in the comments the type was indeed inspired by FP, from Kotlin Arrow to be precise, but it was never intended to behave exactly like it.
1.EitherMustBe()since your foreach will never execute. Compiler is absolutely right in warning about that. - Tanveer BadarEither? If it is a class then your providedFunc<TValid, Either<string, TValid>>can returnnull. Please edit your question to include the complete source code you have as a MCVE. - Progman