I have an internal property on my class that returns List<MyType>
, and I want to employ static checking to help me not do anything dumb in my assembly and possibly add a null to that collection.
I'm getting this static warning on the loop variable of a foreach
over the property.
Warning 149 CodeContracts: Possibly calling a method on a null reference 'myLoopVariable'. Do you expect that System.Collections.Generic.List`1+Enumerator.get_Current returns non-null?
I've never had any problems in the past with my collections containing nulls, but when the compiler and me disagree, it's right and I'm wrong, therefore I want the warning gone. This is just something I never thought of before, and sure enough, I can do MyClass.MyListProperty.Add(null)
, so it is indeed valid.
I can not do Requires
where I use the loop variable, because I get the error:
Contract section within a try block
It let me (without any error) add a Requires
to the method:
Contract.Requires<ArgumentException>(Contract.ForAll<MyClass>(MyClassInstance.MyListProperty, x => x != null))
However, that did not cause the original warning to go away, and also resulted in an additional warning:
Warning 149 CodeContracts: requires unproven: Contract.ForAll(MyClassInstance.MyListProperty, x => x != null)
I'm wondering if there's a way I can put that logic in one place, close to the property definition itself.
What is the mechanism, if any, that code contracts provides to accomplish this?
EDIT:
I am beginning to think I'm going to have to make MyListProperty
private again, and restrict access to it. Otherwise, someone (me) could add a null
to it! (But the challenge there is, how to allow enumeration by a "trusted" visitor? oh my!)
The Assume will get of the message but I am not sure if this will lead to performance issues, also it seems redundant. Unfortunately I could not get rid of the static checker message without using Contract.Assume.
// at the beginning of your method
Contract.Requires(MyCollection != null && Contract.ForAll(MyCollection, x => x != null));
// other code
foreach(var item in MyCollection)
{
Contract.Assume(item != null);
// call method on item which can create a message from the static checker if the assume is not included
}