Contract.Ensures在多个对象/类链代码合同中未经证实

时间:2010-11-17 09:39:57

标签: c# .net code-contracts

我有以下类结构:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics.Contracts;

namespace contractsTest
{
    class Program
    {
        static void Main(string[] args)
        {
            IService s = new Service();
            s.sendMessage(MessagesCreator.TestMessage);
        }
    }

    class Service : IService
    {
        public void DoSomething(Message m)
        {
        }
    }

    static class MessageNames
    {
        public static string TestMessage
        {
            get
            {
                Contract.Ensures(!string.IsNullOrWhiteSpace(Contract.Result<string>()));
                return "TestMessage";
            }
        }
    }

    class Message
    {
        public Message(string _name)
        {
            Contract.Requires<ArgumentNullException>(!string.IsNullOrWhiteSpace(_name));
            Contract.Ensures(this.Name == _name);
            this.Name = _name;
        }

        public string Name { get; private set; }
    }

    static class MessagesCreator
    {
        public static Message TestMessage
        {
            get
            {
                Contract.Ensures(Contract.Result<Message>() != null);
                Contract.Ensures(Contract.Result<Message>().Name == MessageNames.TestMessage);

                return new Message(MessageNames.TestMessage);
            }
        }
    }

    static class Extensions
    {
        public static void sendMessage(this IService service, Message m)
        {
            Contract.Requires<ArgumentNullException>(service != null);
            Contract.Requires<ArgumentNullException>(m != null);
            Contract.Requires<ArgumentNullException>(!string.IsNullOrWhiteSpace(m.Name));

            service.DoSomething(m);
        }
    }

    [ContractClass(typeof(IServiceContract))]
    interface IService
    {
        void DoSomething(Message m);
    }
    [ContractClassFor(typeof(IService))]
    abstract class IServiceContract : IService
    {
        public void DoSomething(Message m)
        {
            Contract.Requires<ArgumentNullException>(m != null);
            Contract.Requires<ArgumentException>(!string.IsNullOrWhiteSpace(m.Name));
            // Do Something           
        }
    }
}

在Main中我得到以下警告CodeContracts:需要未经证实:!string.IsNullOrWhiteSpace(m.Name)

知道怎么解决吗?

如果我将main更改为:

static void Main(string[] args)
{
    IService s = new Service();

    Message messagesCreatorTestMessage = MessagesCreator.TestMessage;

    if (string.IsNullOrWhiteSpace(messagesCreatorTestMessage.Name))
        throw new InvalidOperationException();

    s.sendMessage(messagesCreatorTestMessage);
}

警告消失了,但应该有其他更优雅的方法。

2 个答案:

答案 0 :(得分:3)

Ensures构造函数中的Message仅指定构造函数完成时条件为真;它并不表示条件在Message实例的生命周期内为真。

为此,请使用Contract.Invariant方法:

class Message
{
    [ContractInvariantMethod]
    private void MessageInvariants()
    {
        Contract.Invariant(!string.IsNullOrWhiteSpace(Name));
    }

    public Message(string _name)
    {
        Contract.Requires<ArgumentNullException>(!string.IsNullOrWhiteSpace(_name));
        Contract.Ensures(this.Name == _name);
        this.Name = _name;
    }

    public string Name { get; private set; }
}

答案 1 :(得分:1)

这可能是问题所在:

// In the Message constructor
Contract.Requires<ArgumentNullException>(!string.IsNullOrWhiteSpace(_componentName));

我怀疑你的意思是:

Contract.Requires<ArgumentNullException>(!string.IsNullOrWhiteSpace(_name));

我不清楚_componentName来自哪里......