我有以下类结构:
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);
}
警告消失了,但应该有其他更优雅的方法。
答案 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
来自哪里......