我正在实现一个实现 IDictionary 的类。但我无法匹配 TryGetValue 的代码合同。
这是代码的相关部分:
class Wrapper : IDictionary<string, object>
{
...
IDictionary<string,object> dictionary;
public bool TryGetValue(string key, out object value)
{
var result = dictionary.TryGetValue(key, out value);
Contract.Assume(result == ContainsKey(key));
return result;
}
public bool ContainsKey(string key)
{
Contract.Ensures(Contract.Result<bool>() == dictionary.ContainsKey(key));
return dictionary.ContainsKey(key);
}
...
}
Run Code Online (Sandbox Code Playgroud)
静态分析抱怨:
CodeContracts:确保未经证实:
Contract.Result<bool>() == @this.ContainsKey(key)
我应该怎样做才能满足合同要求?
备注:当密钥是通用的(如 )时,不会出现该问题Wrapper<TKey> : IDictionary<TKey, object>。
我定义了一个具有一个通用方法DoSomething的以下示例类:
public static class MyClass
{
public static void DoSomething<T>(T val)
{
System.Diagnostics.Contracts.Contract.Requires(typeof(T).IsEnum);
}
}
Run Code Online (Sandbox Code Playgroud)
我有以下枚举:
public enum MyEnum { A, B }
Run Code Online (Sandbox Code Playgroud)
现在我使用我的枚举实例调用该方法,如下所示:
class Program
{
static void Main(string[] args)
{
MyClass.DoSomething(MyEnum.A);
}
}
Run Code Online (Sandbox Code Playgroud)
在代码协定中启用静态检查后,在我调用方法的行显示以下警告:
CodeContracts:需要未经证实:typeof(T).IsEnum
如果在编译时知道该值,为什么它未经证实?
编辑
因为这显然不起作用,可能是因为Code Contracts不理解语义IsEnum或val is Enum(Jon也指出).我感兴趣,如果有任何已知的方法在代码合同中进行这种检查?
我有一份合同,这样做:
for (int i = 0; i < delegateParameterTypes.Length; i++)
{
Contract.Assert(i < delegateParameterTypes.Length);
Contract.Assert(delegateParameterTypes.Length == methodParameters.Length + (1));
// Q.E.D.
Contract.Assert(i < methodParameters.Length + (1));
}
Run Code Online (Sandbox Code Playgroud)
前两次通过分析很好,但第三次说断言是未经证实的,一个接一个?考虑后卫.这似乎是简单的数学.有什么我想念的吗?
尝试使用字符串数组和本地值似乎工作正常.可能会以某种方式与.Length电话有关吗?我尝试将int交换到UInt16以查看它是否是由于循环中的缓冲区溢出,但事实并非如此.
在 .net 框架中,有代码契约允许我在代码中指定前置/后置条件。.net core/.net 5 支持它们吗?
我想通过合同跳进编码.我得到了VS2010(使用C#4.0编译器),但我必须针对3.5框架.
合同库的第三方代码是什么类和接口最像.NET 4.0的类?
我正在对代码合同进行简单的测试.以下代码处于winform状态.这通过(当然):
private void Test(Form form)
{
Contract.Requires(!string.IsNullOrEmpty(form.Name));
MessageBox.Show(form.Name);
}
protected override void OnLoad(EventArgs e)
{
if (!string.IsNullOrEmpty(Name))
Test(this);
base.OnLoad(e);
}
Run Code Online (Sandbox Code Playgroud)
但是,我只添加了一个非常简单的间接层,它说"需要未经证实":
private bool Valid(string str)
{
return !string.IsNullOrEmpty(str);
}
protected override void OnLoad(EventArgs e)
{
if (Valid(Name))
Test(this);
base.OnLoad(e);
}
Run Code Online (Sandbox Code Playgroud)
这似乎证明是微不足道的.为什么不工作?
我的库使用代码契约.
有没有办法将这些合同纳入沙堡生成的文档中?
我有这个代码:
public class CodeContractSample
{
private readonly List<object> _items = new List<object>();
public IEnumerable<object> Query()
{
Contract.Ensures(Contract.Result<IEnumerable<object>>() != null);
//if (_items == null) throw new Exception();
return _items;
}
}
Run Code Online (Sandbox Code Playgroud)
CodeContracts给出了这个警告:
CodeContracts:确保未经证实:Contract.Result>()!= null
如果我取消注释中间行,它就会停止抱怨.但为什么一开始就抱怨?_items永远不应该为null ..?
我已经安装了一个插件(Microsoft的Code Contract Editor Extensions),它显示了.NET的所有代码契约.
当我看合同Random.Next,它说 ensures result <= maxValue,而MSDN指出,包括maxValue是排斥的.合同不应该说ensures result < maxValue吗?
最近,我开始使用.net的代码合同.在我看来,代码签约本身的想法很棒,但实现起来非常不愉快.
我不喜欢它的主要原因是:
Contract.Require()我的程序里面的方法.ContractAbbreviators有很多限制(比如,我不能将它们放在一个单独的程序集中,我不能使用参数),这使得它们的可用性降低.没有属性,也没有扩展方法,所以我的代码变得非常冗长.例如,如果我只是想检查我的返回值类型Dictionary<string, string>是否为null,我需要添加一个怪物,如Contract.Ensure(Contract.Result<Dictionary<string, string>> != null).它甚至都不可读.ccrewriter- 它不能咀嚼一半的程序集,并且它无法在.net 4.5运行时中存活.net 4.0程序集.Debug.Assert- 你只需将它们添加到你认为需要的任何地方.但事实证明,我需要向静态检查器证明一切,这是肯定的,但检查器有时是愚蠢的,无法解决许多明显的代码结构(如while).并且没有任何工具可以对分析仪说"我知道我在做什么,只是忽略这违反合同".string.NotNullOrEmpty这包括string != null.或者,如果我有自己的大程序检查文件路径,我无法向分析器解释它肯定不是null而不是空的.该ContractAbbreviator属性帮助一点点,但所有这些冗长去那里,它仍然看起来肮脏和愚蠢的.代码合同是否有任何先进的替代方案,缺陷较少?