代码协定:确保对委托的约束,以避免“需要未经验证”的警告
本文关键字:警告 验证 确保 代码 约束 | 更新日期: 2023-09-27 18:35:39
我有一个类,它允许使用任何对象类型T
类似开关的语句,并允许指定返回类型R
。当我尝试要求非空值时,我收到一条警告,指出它requires unproven: value != null
。认为假设会取消静态检查器的警告,但在运行时强制执行它,但它不执行前者。我有哪些选择?
下面是带有 Contract.Require 语句的类:
public class SwitchReturn<T, R>
{
public SwitchReturn(T o)
{
Contract.Requires(o != null);
Object = o;
}
public T Object { get; private set; }
public bool HasValue { get; private set; }
public R Value { get; private set; }
public void Set(R value)
{
Contract.Requires(value != null); // <== the source of all the troubles
Value = value;
HasValue = true;
}
}
下面是使用未经证实的需求调用代码的示例:
public static SwitchReturn<T, R> Case<T, R>(this SwitchReturn<T, R> s, Func<T, R> f)
{
Contract.Requires(s != null);
Contract.Requires(s.Object != null);
Contract.Requires(f != null);
if (!s.HasValue)
{
Contract.Assume(f(s.Object) != null); // <== does not remove the warning
s.Set(f(s.Object)); // <== this is the cause of the warning
}
return s;
}
我不想删除非空要求。是否可以在 FUNC 参数上放置约束以确保它不返回空值?
f
不知道是纯的。调用它两次可能会给出不同的结果,因此假设第一个结果是非 null 不会说明第二个结果。
您应该能够将结果存储在变量中,添加有关该变量的假设,然后将其传递给其他方法。
if (!s.HasValue)
{
var val = f(s.Object);
Contract.Assume(val != null);
s.Set(val);
}
听起来问题的
原因是T
和R
可能是值类型。在这种情况下,空检查将失败。
解决方案是使用类型约束来要求T
和R
是引用类型。
public class SwitchReturn<T, R>
where T : class
where R : class
{
...
}