代码之家  ›  专栏  ›  技术社区  ›  Bogdan Maxim

确保在多个对象/类链代码契约中未经验证

  •  0
  • Bogdan Maxim  · 技术社区  · 14 年前

    我的班级结构如下:

    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           
            }
        }
    }
    

    总的来说,我得到了以下警告CodeContracts:需要未经验证:!字符串.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 回复  |  直到 14 年前
        1
  •  3
  •   Jeff Ogata    14 年前

    这个 Ensures Message 构造函数只指定在构造函数完成时条件将为true;它不指示在 消息 实例。

    为此,请使用 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; }
    }
    
        2
  •  1
  •   Jon Skeet    14 年前

    有可能这就是问题所在:

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

    我想你的意思是:

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

    我不清楚在哪 _componentName 甚至来自。。。