好吧,这可能是一些黑客攻击,但请忍受我:)背景是我厌倦了一些方法,那些if语句会弄乱整个方法,例如:
public SomeClass DoStuff(string inputStr)
{
SomeClass result =null;
if (IsOpenFilter(inputStr))
{
....
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
所以我在想,如果我可以做这样的事情,那不是很好吗:
public SomeClass DoStuff(string inputStr)
{
Require(IsOpenFilter(inputStr),null);
....
return result;
}
Run Code Online (Sandbox Code Playgroud)
这种情况可能会被某种形式的代码合同所涵盖,如果是这样,请纠正我:)
我们的想法是,如果语句的计算结果为true,则返回null.如果该方法没有返回类型,则只需:Require(IsOpenFilter(inputStr));
所以我想有两个问题,这可以以某种方式完成吗?我对如何通过调用方法进行条件返回感到困惑.
另一个问题是,这是一个好主意吗?monkeypatch这样的语言有点奇怪,但我更喜欢代码读取的方式.如果它可以放在方法上面的属性中,我会更干净:[Require(IsOpenFilter(inputStr))]
我有一些代码与以下逻辑:
//pseudo-code
foreach (element in elementList) {
if (element is whatever)
return element;
}
}
Run Code Online (Sandbox Code Playgroud)
理论上,总有一个元素是什么,所以这个方法应该没有问题.在任何情况下,我都在方法的最后确定了一个断言,以确保:
//pseudo-code
foreach (element in elementList) {
if (element is whatever)
return element;
}
}
Contract.Assert(false, "Invalid state!");
Run Code Online (Sandbox Code Playgroud)
问题是因为这个方法必须返回一些东西,并且编译器不理解断言会破坏程序执行.在使用Contracts之前,在这种情况下,我曾经抛出一个Exception,它解决了这个问题.你会如何处理Contract.Assert()?在Contract.Assert()调用之后返回null或default(element_type),知道它永远不会被调用并关闭编译器吗?或者还有其他更优雅的方式吗?
谢谢
我刚开始在一个现有的中型项目上尝试使用.NET 4中的CodeContracts,我很惊讶静态检查器给出了关于以下代码段的编译时警告:
public class Foo
{
private readonly List<string> strs = new List<string>();
public void DoSomething()
{
// Compiler warning from the static checker:
// "requires unproven: source != null"
strs.Add("hello");
}
}
Run Code Online (Sandbox Code Playgroud)
为什么CodeContracts静态检查器抱怨strs.Add(...)行?strs没有可能成为null的方法,对吗?难道我做错了什么?
说我有以下内容
public T Example(Func<T> f)
{
Contract.Requires(f != null);
Contract.Requires(f() != null); // no surprise, this is an error
...
}
Run Code Online (Sandbox Code Playgroud)
有没有办法指定我的Func<T>参数必须遵守某些合同?
请考虑以下代码:
int SomeField;
void Foo([Pure] Func<int, object> getData)
{
Contract.Requires(getData != null);
Contract.Requires(getData(this.SomeField) != null);
}
Run Code Online (Sandbox Code Playgroud)
我收到以下警告:
在方法合同中检测到对方法的调用'
System.Func'2<System.Int32,System.Object>.Invoke(System.Int32)' '[Pure]Foo(System.Func'2<System.Int32,System.Object>)
这个警告非常有意义.但是我还是想在合同中给代表打电话而不是警告(假设我的警告变成了错误).我如何实现这一目标?
我尝试了该属性Pure,如示例所示,但这不起作用.
我也想知道为什么PureAttribute可以在参数上指定.如果参数的类型不是委托类型是没有意义的,即使它是,它也不像我期望的那样工作,如上所述.
我想从CodeContracts实现以下建议:
CodeContracts: MyModule: Method MyModule.MyClass.MyMethod:
To mask *all* warnings issued like the precondition add the attribute:
[SuppressMessage("Microsoft.Contracts", "RequiresAtCall-propertyAccessor != null")]
to the method
System.Linq.Expressions.Expression.Property(System.Linq.Expressions.Expression,System.Reflection.MethodInfo)
Run Code Online (Sandbox Code Playgroud)
感觉我应该能够使用具有Target属性的SupressMessage来实现这一点.但是,因为这是一个Framework方法,我不确定.
//doesn't work
[module: SuppressMessage("Microsoft.Contracts", "RequiresAtCall-propertyAccessor != null", Scope = "Member", Target = "System.Linq.Expressions.Expression.Property(System.Linq.Expressions.Expression,System.Reflection.MethodInfo)", Justification = "This isn't covered by Linq Contracts yet.")]
Run Code Online (Sandbox Code Playgroud)
如何全局抑制此警告,因此我不必基线或抑制所有呼叫站点警告?
EDIT: The specific usage that requires this measure is:
void mymethod()
{
var myObserver = new PropertyObserver<MyViewModel>();
//this line throws the error, within the n => n.Value expression
myObserver.RegisterHandler(n => …Run Code Online (Sandbox Code Playgroud) 我看到了C#Code Contracts的一个很棒的演示,我想开始在may代码中实现它们.我希望我已经在我的代码中拥有它们了.一个人从哪里开始?
我没有带走演示中的任何印刷材料.有兴趣吗?
有关代码合同的初学者的任何建议?
在此先感谢您的帮助.
根据此答案, C#现在具有“代码约定”,该代码约定应该可用,而不是C ++编译时断言。现在我有了这个魔术代码:
IntPtr pointer;
//blahblahblah
pointer = new IntPtr(pointer.ToInt32() + Marshal.SizeOf(typeof(SomeStruct)));
Run Code Online (Sandbox Code Playgroud)
需要IntPtr是相同大小的Int32。所以我想要一个编译时间断言-像这样的C ++代码
static_assert(sizeof(IntPtr)==sizeof(Int32))
Run Code Online (Sandbox Code Playgroud)
所以我尝试了以下方法:
System.Diagnostics.Contracts.Contract.Assert(false); //just to test it
pointer = new IntPtr(pointer.ToInt32() + Marshal.SizeOf(typeof(SomeStruct)));
Run Code Online (Sandbox Code Playgroud)
我false进入Assert()以便它肯定会失败,但是编译通过就可以了。
那么,如何使用代码协定来声明编译时间呢?
我正在尝试Code Contract,我遇到了一个问题.我有课:
public class SpecialPoint
{
public int X { get; set; }
public int Y { get; set; }
public SpecialPoint(int x, int y)
{
Contract.Requires<ArgumentException>(y > x);
X = x;
Y = y;
}
[ContractInvariantMethod]
private void ClassContract()
{
Contract.Invariant(Y > X);
}
}
Run Code Online (Sandbox Code Playgroud)
我对它进行了一次测试:
[TestFixture]
class SpecialPointTests
{
[Test]
public void SpecialPoint()
{
var p = new SpecialPoint(10, 20);
p.X = 30;
}
}
Run Code Online (Sandbox Code Playgroud)
我希望静态检查器警告我有关赋值pX = 30; 因为这违反了不变量,但它只发生在运行时.我有静态分析启用.我的版本是1.7.11202.10.
我有一段看起来像这样的代码:
public TReturn SubRegion(TParam foo)
{
Contract.Requires(foo!= null);
Contract.Ensures(Contract.Result<TReturn>() != null);
if (!CheckStuff(foo))
foo.Blah();
return OtherStuff(foo);
}
Run Code Online (Sandbox Code Playgroud)
CC正在给我一个警告:
警告301 CodeContracts:考虑添加后置条件Contract.Ensures(Contract.Result()!= null); 为库客户提供额外的文档
这显然是多余的!我有几个这样的冗余警告,它正在成为一个问题(真正的警告被埋没在多余的冗余建议中).
所以我有两个问题:
1)我错过了什么意味着这不是一个多余的建议吗?在这种情况下,我需要做些什么来修复此警告?
2)或者,如果这只是CCCheck的一个怪癖并且无法修复,我如何隐藏或抑制此警告?
注:万一你觉得我的例子缺少一些重要的东西,全部代码是区域SubRegion1方法在这里.