引用另一个约定方法时是否应该重复条件?

发布于 2025-01-05 09:57:40 字数 549 浏览 0 评论 0原文

以下是接口合约的摘录。

我的问题是:前一种方法是否应该重复后一种方法的前提条件?由于合同是公开的,是否可以省略重复?在这种情况下,它只是一个非空检查,但我可以想象这样的情况:重复大量代码并且由于在运行时重复相同的检查而导致性能受到影响。

public int CommandConsumerCount(IWriteCommand writeCommand)
{
    Contract.Requires(writeCommand != null); // redundant?
    Contract.Requires(this.IsOwnerOf(writeCommand));

    Contract.Ensures(Contract.Result<int>() >= 0);

    return default(int);
}

public bool IsOwnerOf(IWriteCommand writeCommand)
{
    Contract.Requires(writeCommand != null);

    return default(bool);
}

The following is an extract from an interface contract.

My question is: should the former method repeat the pre-conditions of the latter method? As the contracts are public, would it be acceptable to omit the repetition? In this case it's simply a non-null check, but I can imagine the situation where a lot of code is repeated and performance suffers as identical checks are repeated at runtime.

public int CommandConsumerCount(IWriteCommand writeCommand)
{
    Contract.Requires(writeCommand != null); // redundant?
    Contract.Requires(this.IsOwnerOf(writeCommand));

    Contract.Ensures(Contract.Result<int>() >= 0);

    return default(int);
}

public bool IsOwnerOf(IWriteCommand writeCommand)
{
    Contract.Requires(writeCommand != null);

    return default(bool);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

爱已欠费 2025-01-12 09:57:40

这在某种程度上取决于该条件(在本例中为 writeCommand != null)是否是 CommandConsumerCount 方法和 IsOwnerOf 方法的要求,或者是否仅是 IsOwnerOf 方法的要求。

如果该条件仅是 IsOwnerOf 方法真正需要的,那么可以从 CommandConsumerCount 方法中省略它。

但是,如果这两种方法都需要该条件,那么我支持下面的原始答案:

我认为因为您的两种方法都是公开的,所以应该重复合同要求。如果您有一个执行实际工作的私有方法,IsOwnerOf 方法和 CommandConsumerCount 方法都调用该方法(而不是调用 IsOwnerOf 方法的 CommandConsumerCount 方法),那么在该方法中省略对 Contract.Requires 的调用就可以了。私有方法。

就性能而言......我不会担心这些检查对性能的影响,除非检查本身的逻辑非常复杂。您可以设置编译器以从项目属性的“代码合同”部分的编译输出中排除对 Contract.Requires 的调用(假设您安装了必要的插件)。

不过,也许我没有抓住你问题的重点。您是否询问是否可以完全省略 CommandConsumerCount 方法内部对 IsOwnerOf 的调用?在这种情况下,我会将调用保留在适当的位置,但如果这是一个性能问题,那么我将配置项目以排除对发布版本的调用,假设我已经使用调试版本进行了足够的测试以确保此条件是满意。

编辑:重新阅读问题后,很明显您正在询问 writeCommand != null 检查,因此我删除了上面的段落。

下面的代码示例添加了执行 IsOwnerOf 方法的实际工作的私有方法。

    // you may want to choose a different name for this method
    private bool _IsOwnerOf(IWriteCommand)
    {
        // actual work is done here in this private method
        return default(bool);
    }

    public bool IsOwnerOf(IWriteCommand writeCommand)
    {
        Contract.Requires(writeCommand != null);

        // call the private method to perform the actual work
        return _IsOwnerOf(writeCommand);
    }

    public int CommandConsumerCount(IWriteCommand writeCommand)
    {
        Contract.Requires(writeCommand != null);
        Contract.Requires(_IsOwnerOf(writeCommand)); // call the private _IsOwnerOf method instead of the public method

        Contract.Ensures(Contract.Result<int>() >= 0);

        return default(int);
    }

It kind of depends on whether that condition (writeCommand != null in this case) is a requirement for both the CommandConsumerCount method as well as the IsOwnerOf method, or if it is only a requirement for the IsOwnerOf method.

If that condition is only really required by the IsOwnerOf method, then it would be ok to omit it from the CommandConsumerCount method.

However, if that condition is required by both methods, then I stand by my original answer below:

I think that because both of your methods are public that the contract requirements should be repeated. If you had a private method that did the actual work, which both the IsOwnerOf method and the CommandConsumerCount method called (instead of the CommandConsumerCount method calling the IsOwnerOf method), then it would be fine to omit the call to Contract.Requires inside of that private method.

As far as performance goes...I wouldn't be concerned about the performance impact of these checks, unless the logic for the checks themselves is very complicated. You can set up the compiler to exclude those calls to Contract.Requires from the compiled output in the "Code Contracts" section of the project properties (assuming you have the necessary plugin installed).

Perhaps I'm missing the point of your question, though. Are you asking if it's OK to completely omit the call to IsOwnerOf inside of the CommandConsumerCount method? In that case I would leave the call in place, but if it's a performance concern, then I would configure the project to exclude that call for Release builds, assuming that I've done sufficient testing with a Debug build to ensure that this condition is satisfied.

EDIT: after re-reading the question, it seems clear that you're asking about the writeCommand != null check, so I've struck out the above paragraph.

Code example below of adding a private method that performs the actual work of the IsOwnerOf method.

    // you may want to choose a different name for this method
    private bool _IsOwnerOf(IWriteCommand)
    {
        // actual work is done here in this private method
        return default(bool);
    }

    public bool IsOwnerOf(IWriteCommand writeCommand)
    {
        Contract.Requires(writeCommand != null);

        // call the private method to perform the actual work
        return _IsOwnerOf(writeCommand);
    }

    public int CommandConsumerCount(IWriteCommand writeCommand)
    {
        Contract.Requires(writeCommand != null);
        Contract.Requires(_IsOwnerOf(writeCommand)); // call the private _IsOwnerOf method instead of the public method

        Contract.Ensures(Contract.Result<int>() >= 0);

        return default(int);
    }
淑女气质 2025-01-12 09:57:40

一般来说,如果方法A调用方法B,那么A必须确保B上的所有合约都是true。

但是,如果该方法用在 Requires 中,那就是多余的,因为所有 Requires 都必须由该方法的调用者证明。

例如,如果您有:

CommandConsumerCount(x);

没有有关 x 的信息,则静态检查器将抱怨 IsOwnerOf 必须为 true。为了证明 IsOwnerOf,您的代码必须执行以下操作:

if (IsOwnerOf(x))
{
    CommandConsumerCount(x);
}

或者:

IWriteCommand GetWriteCommand()
{
    Contract.Ensures(IsOwnerOf(Contract.Result<IWriteCommand>()));

    //...
}

var x = GetWriteCommand();
CommandConsumerCount(x);

在这两种情况下,也会检查 IsOwnerOf 非空合约,因此参数被证明不为空。

但是,如果您将 CommandConsumerCount 改为这样:

int CommandConsumerCount(IWriteCommand command)
{
    Contract.Requires(command != null);

    if (IsOwnerOf(command))
    {
       // ...
    }

    return 0;
}

在这种情况下,CommandConsumerCount 将需要合约,因为调用者没有义务证明 IsOwnerOf 为 true,因此不会检查非空合约。

Generally, if method A calls method B, then A must ensure that all contracts on B are true.

However, if the method is used in a Requires, it is redundant, since all Requires must be proven by the caller of the method.

For example, if you have:

CommandConsumerCount(x);

With no information about x, then the static checker will complain that IsOwnerOf is required to be true. In order to prove IsOwnerOf, your code must do something like this:

if (IsOwnerOf(x))
{
    CommandConsumerCount(x);
}

or:

IWriteCommand GetWriteCommand()
{
    Contract.Ensures(IsOwnerOf(Contract.Result<IWriteCommand>()));

    //...
}

var x = GetWriteCommand();
CommandConsumerCount(x);

In both these cases, the IsOwnerOf not-null contract will also be checked, and so the argument is proven to not be null.

However, if you had CommandConsumerCount be something like this instead:

int CommandConsumerCount(IWriteCommand command)
{
    Contract.Requires(command != null);

    if (IsOwnerOf(command))
    {
       // ...
    }

    return 0;
}

In this case CommandConsumerCount would need the contract, since there is no obligation for the caller to prove that IsOwnerOf is true, and so the not-null contract will not have been checked.

世俗缘 2025-01-12 09:57:40

我想说的是,每个方法应该只指定它需要的条件,而忽略它调用的条件方法。

因此,如果CommandConsumerCount需要writeCommand不为null,那么拥有合约并不多余。

但是,如果 CommandConsumerCount 需要 writeCommand 不为 null 的唯一原因是将其传递给 IsOwnerOf,那么它是多余的。

I would say that each method should specify only the conditions that it needs and be ignorant of the conditions methods it calls.

So if CommandConsumerCount needs writeCommand to not be null, then it is not redundant to have the contract.

However if the only reason CommandConsumerCount needs writeCommand to not be null is to pass it to IsOwnerOf, then it is redundant.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文