我有一个类,它允许使用任何对象类型T
的类似开关的语句,并允许指定返回类型R
。当我尝试要求非空值时,我会收到警告requires unproven: value != null
。想象一下,假设会带走静态检查器的警告但在运行时强制执行它,但它不会执行前者。我有什么选择?
这是包含Contract.Requires语句的类:
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;
}
我不想删除非null要求。是否可以在FUNC参数上设置约束,确保它不返回空值?
答案 0 :(得分:1)
f
并不是纯粹的。调用它两次可能会得到不同的结果,所以假设第一个结果是非null,则说明第二个结果。
您应该能够将结果存储在变量中,添加关于该变量的假设,然后将其传递给您的其他方法。
if (!s.HasValue)
{
var val = f(s.Object);
Contract.Assume(val != null);
s.Set(val);
}
答案 1 :(得分:0)
听起来问题的原因是T
和R
可能是值类型。在这种情况下,空检查将失败。
解决方案是使用类型约束来要求T
和R
作为引用类型。
public class SwitchReturn<T, R>
where T : class
where R : class
{
...
}