我们正在迁移到.NET 4,并且对实现新的按设计合同功能非常感兴趣.
我们知道Code Contract引擎需要安装Code Contract addin

和VS Ultimate或Premium(用于静态检查).
这是我的问题:
(也发布在MSDN论坛上 - 但据我所知,这并没有太大的流量.)
我一直试图提供一个Assert和的例子Assume.这是我得到的代码:
public static int RollDice(Random rng)
{
Contract.Ensures(Contract.Result<int>() >= 2 &&
Contract.Result<int>() <= 12);
if (rng == null)
{
rng = new Random();
}
Contract.Assert(rng != null);
int firstRoll = rng.Next(1, 7);
Contract.Assume(firstRoll >= 1 && firstRoll <= 6);
int secondRoll = rng.Next(1, 7);
Contract.Assume(secondRoll >= 1 && secondRoll <= 6);
return firstRoll + secondRoll;
}
Run Code Online (Sandbox Code Playgroud)
(关于能够传入空引用而不是现有Random引用的业务当然是纯粹的教学法.)
我曾希望如果检查员知道firstRoll并且secondRoll每个都在范围内[1, 6],那么就可以计算出总和在范围内[2, 12].
这是一个无理的希望吗?我意识到这是一项棘手的事情,确切地说明可能会发生什么......但我希望检查器足够聪明:)
如果现在不支持这个,那么这里是否有人知道它是否可能在近期未来得到支持? …
我想使用代码合同为此通用接口指定合同:
interface IRandomWriteAccessible<T>
{
T this[uint index] { set; }
uint Length { get; }
}
Run Code Online (Sandbox Code Playgroud)
文档ContractClass说明在为接口指定合同时使用该属性.但是,编译器会抱怨这个:
[ContractClass(typeof(IRandomWriteAccessibleContract<T>))]
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ <-- compiler error
interface IRandomWriteAccessible<T> { … }
[ContractClassFor(typeof(IRandomWriteAccessible<T>))]
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ <-- compiler error
sealed class IRandomWriteAccessibleContract<T> : IRandomWriteAccessible<T> { … }
Run Code Online (Sandbox Code Playgroud)
似乎类型参数不能与属性一起使用.
如何做我写我的通用接口一份合同吗?或者代码合同无法实现这一点吗?
这两个陈述之间有什么不同?
Contract.Requires(string.IsNullOrWhiteSpace(userName));
Contract.Assume(string.IsNullOrWhiteSpace(userName));
Run Code Online (Sandbox Code Playgroud) 考虑以下两段代码:
public static Time Parse(string value)
{
string regXExpres =
"^([0-9]|[0-1][0-9]|2[0-3]):([0-9]|[0-5][0-9])$|^24:(0|00)$";
Contract.Requires(value != null);
Contract.Requires(new Regex(regXExpres).IsMatch(value));
string[] tokens = value.Split(':');
int hour = Convert.ToInt32(tokens[0], CultureInfo.InvariantCulture);
int minute = Convert.ToInt32(tokens[1], CultureInfo.InvariantCulture);
return new Time(hour, minute);
}
Run Code Online (Sandbox Code Playgroud)
和
public static Time Parse(string value)
{
if (value == null)
{
throw new ArgumentNullException("value");
}
string[] tokens = value.Split(':');
if (tokens.Length != 2)
{
throw new FormatException("value must be h:m");
}
int hour = Convert.ToInt32(tokens[0], CultureInfo.InvariantCulture);
if (!(0 <= hour && hour <= 24)) …Run Code Online (Sandbox Code Playgroud) 我正在使用代码合同并试图了解我将使用哪些构建选项以及何时使用.合同装配构建选项在项目属性中定义
代码合同 - >合同参考汇编:
有什么想法或建议吗?
我一直在玩新的System.Diagnostics.Contracts类,因为它起初看起来非常有用.用于检查入站参数,返回值等的静态方法.它是一个干净的接口,可以替换许多if-then语句和内部构建的库工具.
但是,它在大多数运行时情况下似乎不太有用.据我所知,它不会引发错误,所以我无法知道合同是否失败.它会弹出一个带有错误的对话框.如果我在远程盒子上运行wcf服务,很少有人看它...我怎么知道合同失败了?如果我无法捕捉错误发生的事实,我怎么能让服务的来电者知道他们已经搞砸了?
Throw-Catch已经存在了一段时间,我不明白为什么合同想绕过这个.我试图错误地使用这个东西吗?如果是这样,那么有人会给我一个真实的情况,其中运行时契约是有意义的.肯
我有以下代码合同:
public void F(string x)
{
Contract.Requires(!string.IsNullOrWhiteSpace(x));
throw new NotImplementedException();
}
Run Code Online (Sandbox Code Playgroud)
编译时,我收到以下警告:
警告CC1036:在方法合同中检测到方法'System.String.IsNullOrWhiteSpace(System.String)'没有[Pure]的调用[...]
怎么处理呢?
奇怪的是,我也在使用string.IsNullOrEmpty,[Pure]其他合同中没有标记,并且重写者没有问题.
我的合同重写版的版本是1.9.10714.2.
这是String我正在使用的类(从元数据中检索)的实现的相关部分:
#region Assembly mscorlib.dll, v4.0.0.0
// C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\mscorlib.dll
#endregion
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
namespace System
{
// Summary:
// Represents text as a series of Unicode characters.To browse the .NET Framework
// source code for this type, see the Reference Source.
[Serializable]
[ComVisible(true)]
public …Run Code Online (Sandbox Code Playgroud) 我从Visual Studio 2010中获得了Code Contracts,但我无法ccrewrite.exe从命令行做任何有用的事情.这是一个示例应用程序:
using System.Diagnostics.Contracts;
public class Dummy
{
public static void Main(string[] args)
{
Contract.Requires(args.Length > 0);
}
}
Run Code Online (Sandbox Code Playgroud)
然后我编译代码并在其上运行ccrewrite.exe:
> csc /debug+ /D:CONTRACTS_FULL Dummy.cs
> ccrewrite /o:RewrittenDummy.exe Dummy.exe
elapsed time: 61ms
Run Code Online (Sandbox Code Playgroud)
RewrittenDummy.exe之后没有文件.
我已经尝试了很多选项,但没有任何区别.我注意到的一些事情:
我已经尝试过警告和冗长,这根本没有帮助我做错了什么?
我正在对Visual Studio进行扩展.在代码中,我使用代码约定来进行断言和检查.我将警告选项级别设置为高.
我想要做的是保持警告级别,同时忽略对EnvDTE引用进行的任何检查.
请考虑以下代码示例:
public static string GetAbsoluteOutputFolder(EnvDTE.Project project)
{
if (project == null) throw new ArgumentNullException("project");
var path =
project.ConfigurationManager.ActiveConfiguration.Properties.Item("OutputPath").Value.ToString();
//...
}
Run Code Online (Sandbox Code Playgroud)
使用我当前的设置,CC会要求我在分配path变量之前添加以下检查:
Contract.Assume(project.ConfigurationManager != null);
Contract.Assume(project.ConfigurationManager.ActiveConfiguration != null);
Contract.Assume(project.ConfigurationManager.ActiveConfiguration.Properties != null);
Run Code Online (Sandbox Code Playgroud)
因此,我想在这里做的是告诉CC"信任"EnvDTE并忽略这些类型及其属性.
我认为"乐观外部API"CC选项就是为了这个目的而服务的.事实证明它没有.
有没有办法让它按照我想要的方式运行,不需要较低的警告级别?
编辑:我想要一个在项目级别工作的解决方案,并且仍然允许执行"常规"检查.