Chr*_*ter 59 c# code-contracts
我终于在.NET 3.5/4.0框架中添加了所有新内容.最近几天我一直在使用CodeContracts,我真的很努力喜欢它们.我很好奇其他人对C#中CodeContracts的实现有何看法?具体来说,人们如何组织诸如接口的合同类,合同不变量的合同方法等等?
我喜欢合同提供的验证,乍一看它们看起来很棒.通过一些简单的行,我可以在运行代码之前获得一些很好的构建检查.不幸的是,我很难理解代码契约在C#中实现的方式,它们使我的代码比记录合同更加混乱.为了充分利用合同,我在假设和断言等方面乱丢我的代码(我知道有些人会说这是好事); 但正如我下面的一些例子所示,它将一条简单的行转换为4或5行,并且在我看来并没有真正增加其他方法(即断言,异常等)的足够价值.
目前,我最大的挫折是:
界面合同:
[ContractClass(typeof(IInterfaceContract))]
public interface IInterface
{
Object Method(Object arg);
}
[ContractClassFor(typeof(IInterface))]
internal abstract class IInterfaceContract
{
private IInterfaceContract() { }
Object IInterface.Method(Object arg)
{
Contract.Requires(arg != null);
Contract.Ensures(Contract.Result<Object>() != null);
return default(Object);
}
}
Run Code Online (Sandbox Code Playgroud)
这感觉就像这样一个cludge对我来说,我希望有一个更清洁的记录要求的方式,无论是通过属性或某种形式的内置的语言支持.我有这样的事实来实现,实现我的接口一个抽象类,只是让我可以指定合约似乎有些单调乏味的最好的.
代码膨胀:
typeof(Action<>).MakeGenericType(typeof(Object);
Run Code Online (Sandbox Code Playgroud)
需要几个假设才能验证现有的信息.我明白,所有的分析都知道的是,它是在型操作,因此必须在有限的知识工作,但它仍然让我很沮丧的是一个单一的代码行要求我重新写为
var genericAction = typeof(Action<>);
Contract.Assume(genericAction.IsGenericType);
Contract.Assume(genericAction.GetGenericArguments().Length == 1);
genericAction.MakeGenericType(typeof(Object));
Run Code Online (Sandbox Code Playgroud)
只是为了记录事情(是的,我知道我可以使用ContractVerificationAttribute来关闭方法/类等,或者使用SuppressMessageAttribbute来定位特定的消息,但这似乎打败了目的,因为你的代码很快就会被抑制等等所困扰.
另外,以案例为例
public class MyClass
: IInterface
{
private readonly Object _obj;
public Object Property
{
get
{
Contract.Ensures(Contract.Result<Object>() != null);
return _obj;
}
}
public MyClass(Object obj)
{
Contract.Requires(obj != null);
_obj = obj;
}
}
Run Code Online (Sandbox Code Playgroud)
obj必须不为null,并且设置为无法更改的只读字段,但我仍然需要在我的类中添加"标记"方法,以便可以证明我的属性要求不返回null:
[ContractInvariantMethod]
private void ObjectInvariant()
{
Contract.Invariant(_obj != null);
}
Run Code Online (Sandbox Code Playgroud)
还有更多,但我认为我可能已经足够大了,我真的很感激那些比我更聪明的人的洞察力来帮助我"喜欢"代码合同并让这种代码杂乱的感觉消失.任何有关如何更好地构建代码,解决方法令人讨厌的问题等的见解将不胜感激.
谢谢!
por*_*ges 26
这感觉就像这样一个cludge对我来说,我希望有一个更清洁的记录要求的方式,无论是通过属性或某种形式的内置的语言支持.
CC团队已经声明使用属性不够强大,因为你不能在其中包含lambdas之类的东西.他们可能会包含类似[NotNull]但却选择不这样做的事情,因为他们试图尽可能保持CC的一般性.
CC是库(而不是扩展C#的一部分)的一个原因是它支持所有 .NET语言.
您可以在此处阅读有关团队推理的更多信息.
在实际使用它方面,到目前为止我只是将接口契约保留在与接口相同的文件中,这意味着它们都记录在同一个地方.这是应该改进的东西:)
代码膨胀[...]
您的第二个投诉可能是可以实施的 - 我建议将其发布在代码合同论坛上.(编辑:似乎有人已经有,但还没有答案.)
但是,指定合同不足的情况总是需要更多的假设.如果您在.NET框架中遇到这样的情况,您可以请求在缺少的Libraries Contracts线程中添加合同.
此外,采取类似[...]的案例
这已得到解决.如果您有自动属性,则只需添加非null不变量,将生成前/后条件:
public class MyClass : IInterface
{
private Object Property { get; set; }
[ContractInvariantMethod]
private void Invariants()
{
Contract.Invariant(Property != null);
}
}
Run Code Online (Sandbox Code Playgroud)
无论如何,你最终可能会为你的课程设置其他不变量,所以这并不是什么大不了的事.
Mat*_*son 12
是的,合同搞砸了,但是当PEX读取代码合同并为我生成25个单元测试和100%代码覆盖时,我觉得这是值得的.如果你还没有使用过PEX,那么你就错过了代码合同的最大好处.这是使用PEX与合同的入门指南.
我真的很想也喜欢它,并且在一个新项目的实施中走得很远,直到我放弃了我用它的小问题.
我希望微软能够复活Spec#.我知道代码契约是作为一个可以跨语言使用的库编写的,但即便只是静态分析的速度也需要编译器支持.
这家伙提出了一些相同的观点:http://earthli.com/news/view_article.php?id = 2183
无论如何,没有一个问题是一个交易破坏者,但积累的烦恼:
Contract.Assume(thing != null)| 归档时间: |
|
| 查看次数: |
13091 次 |
| 最近记录: |