I just started experimenting with CodeContracts in .NET 4 in an existing medium-sized project, and I am surprised that the static controller gives me warnings when compiling the following code snippet:
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"); } }
Why does the CodeContracts static controller complain about the string strs.Add (...)? There is no way for strs to be null, is there? Am I doing something wrong?
readonly, , , . , , strs , :
readonly
strs
[ContractInvariantMethod] private void ObjectInvariant() { Contract.Invariant(strs != null); }
, .
public class Foo { private readonly List<string> strs = new List<string>(); public Foo() { // strs is readonly, so we can assign it here but nowhere else strs = ResultOfSomeFunction(); } public void DoSomething() { // Compiler warning from the static checker: // "requires unproven: source != null" strs.Add("hello"); } }
, , , , strs. , , - strs , .
: Pex Z3, SMT-, Clousot ( ) .
.NET, . :
null
Contract.Assume
Contract.Assert
Interestingly, if you explicitly add an Object Invariant Assertion, which can strsnever be null, CC can prove it and therefore can also prove that it strs.Add()will never be an empty reference:
strs.Add()
[ContractInvariantMethod] private void StrsIsNotNull() { Contract.Invariant(strs != null); }
So, I assume that my guess number 2 is correct: CC is simply wrong in this case. (Or more precisely: coding the semantics of C # in theoretical proof is incomplete.)