代码协定:确保对委托的约束,以避免“需要未经验证”的警告

本文关键字:警告 验证 确保 代码 约束 | 更新日期: 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);
}
听起来问题的

原因是TR可能是值类型。在这种情况下,空检查将失败。

解决方案是使用类型约束来要求TR是引用类型。

public class SwitchReturn<T, R>
   where T : class
   where R : class
{
   ...
}