2010-11-17 63 views
0

我有以下類的結構:Contract.Ensures在多個對象/類鏈碼未經證實的合同

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:要求未經證實!string.IsNullOrWhiteSpace(m.Name)

任何想法如何解決它?

如果我改變主要以:

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

    Message messagesCreatorTestMessage = MessagesCreator.TestMessage; 

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

    s.sendMessage(messagesCreatorTestMessage); 
} 

警告消失,但應該有這樣做的其他更優雅的方式。

+0

此外,還需要對代碼契約 – 2010-11-17 10:08:10

回答

1

這是可能的,這就是問題所在:我懷疑你的意思是

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

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

這不是很清楚,我在那裏_componentName甚至來自...

+0

對不起激活全靜態檢查..我想念類型的 – 2010-11-17 09:54:57

+0

@Bogdan:如果你輸入你的代碼,那麼它顯然不是實際給你的錯誤代碼。它也不完整 - 例如沒有服務類。請給出一個簡短但完整的程序來說明問題。 – 2010-11-17 10:06:09

+0

我已更正程序。 – 2010-11-17 10:07:41

3

EnsuresMessage構造函數中只指定了當構造函數完成時條件爲真;但並不表示該條件將在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; } 
} 
相關問題