【发布时间】:2023-04-06 21:20:01
【问题描述】:
我几乎成功地将我的一个库更新为“可空感知”。但是下面的代码给我带来了麻烦。
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;
}
}
}
编译器用[CS8603] Possible null reference return 给我一个return 警告,我可以理解,因为我用null 初始化result。然而,该方法永远不会真正返回 null,result 将始终是来自 validator 的最新返回值。
pragma warning diable 是我唯一的选择,还是我错过了什么?我应该补充一点,我不想更改方法 Either 的返回类型(同样,它应该是 null 安全的)。
编辑:将类 Either 重命名为 Result(返回类型),因为它分散了问题的注意力。还包括类的代码。正如在 cmets 中所问的那样,该类型确实受到了 FP 的启发,确切地说是来自 Kotlin Arrow,但它从未打算表现得完全像它。
【问题讨论】:
-
请edit 将您的完整源代码包含在minimal reproducible example 中,其他人可以编译和测试。还包括您从编译器获得的完整警告,包括行号。
-
如果您编写类似
1.EitherMustBe()的代码,则返回值将为空,因为您的 foreach 永远不会执行。编译器对此的警告是绝对正确的。 -
@TanveerBadar 正如我的评论所说,这不可能发生。但我包含了完整的代码来显示检查。但是,问题很可能是无法通过该支票提取。
-
但那是运行时,我不确定编译器有多聪明。它可能仍会得出与我进行检查时相同的结论。
-
@Index 什么是
Either?如果它是一个类,那么您提供的Func<TValid, Either<string, TValid>>可以返回null。请edit您的问题包括您作为 MCVE 拥有的完整源代码。
标签: c# c#-8.0 nullable-reference-types