Code Contracts: Ensure unproven on string method

我们两清 提交于 2019-12-12 05:28:08

问题


I'm playing around with code contracts and got a simple method inserting a given count of space characters between each character.

e.g.

Hello -> H e l l o
World -> W   o   r   l   d

The method InsertSpaceBetweenLetters is implemented within a class that offers some string-property S, the string that should be returned after modification. Here's the code

public string InsertSpaceBetweenLetters(int spaceWidth)
{
    Contract.Requires(spaceWidth > 0);
    Contract.Requires(S.Length > 0);
    Contract.Ensures(Contract.Result<string>() != null);
    Contract.Ensures(Contract.Result<string>().Length == S.Length + (S.Length - 1) * spaceWidth);

    string result = String.Empty;

    Contract.Assume(S.Length >= 0);
    for(int i = 0; i < S.Length; i++)
    {
        result += S[i];
        if (i < S.Length - 1)
            result += new String(' ', spaceWidth);
    }
    return result;
}

The static checker gives me the following warning:

ensures unproven: Contract.Result<string>().Length == S.Length + (S.Length - 1) * spaceWidth

I thought I could get rid of this warning with the assumption I'm doing before the loop:

Contract.Assume(S.Length >= 0);

But the warning is still there. What assumptions have to be made to get rid of the warning?

Thank you in advance.


回答1:


Fundamentally, I think you're asking too much of the static checker in this case. It would be pretty impressive if it really could work that out. In this case I think you'll just have to live with it being an execution-time check rather than a compile-time check.

I don't know if there's a specific way of saying "please ensure this as a post-condition, but don't try to prove it" - calling Contract.Assume with the post-condition at the end of the method may do it, but it would probably mean evaluating it twice :(

(As an aside, your implementation is currently really inefficient. That's not the topic of this question, but is still worth looking at.)




回答2:


I think your assumption is wrong. It doesn't hold for S.Length == 0: in the second ensures you would get a negativ value.

Second, it's not trivial to check your ensures statement on compile time. Probably just not implemented in the checker..

Maybe you could implement your loop differently. Remove your if statement and loop from 0 to S.Length-2. But I'm not sure..




回答3:


Try this

        public string InsertSpaceBetweenLetters(string S, int spaceWidth) {

        Contract.Requires(spaceWidth > 0);
        Contract.Requires(S != null);
        Contract.Requires(S.Length > 0);
        Contract.Ensures(Contract.Result<string>() != null);
        Contract.Ensures(Contract.Result<string>().Length == S.Length + (S.Length - 1) * spaceWidth);

        StringBuilder result = new StringBuilder(String.Empty);

        int count = 0;
        int final = S.Length - 1;
        foreach ( char c in S )
        {
            result.Append(c, 1);
            if ( count < final )
            {
                result.Append(' ', spaceWidth);
            }
            ++count;
        }
        return result.ToString();
    }


来源:https://stackoverflow.com/questions/13491714/code-contracts-ensure-unproven-on-string-method

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!