Code contracts, forall and custom enumerable - c#

I am using C# 4.0 and Code Contracts and I have my own custom GameRoomCollection : IEnumerable<GameRoom>.
I want to ensure, that no instances of GameRoomCollection will ever contain a null value element. I don't seem to be able to this, though. Instead of making a general rule, I have tried to do a plain and simple example. The AllGameRooms is an instance of GameRoomCollection.
private void SetupListeners(GameRoom newGameRoom) {
Contract.Requires(newGameRoom != null);
//...
}
private void SetupListeners(Model model) {
Contract.Requires(model != null);
Contract.Requires(model.AllGameRooms != null);
Contract.Assume(Contract.ForAll(model.AllGameRooms, g => g != null));
foreach (GameRoom gameRoom in model.AllGameRooms)
SetupListeners(gameRoom);//<= Warning: Code Contracts: Requires unproven: newGameRoom != null
}
Can anyone see, why I haven't proven, that gameRoom is not null?
EDIT:
Adding a reference for the object before iterating does not work either:
IEnumerable<IGameRoom> gameRooms = model.AllGameRooms;
Contract.Assume(Contract.ForAll(gameRooms, g => g != null));
foreach (IGameRoom gameRoom in gameRooms)
SetupListeners(gameRoom);//<= Warning: Code Contracts: Requires unproven: newGameRoom != null
EDIT2:
However: If I convert the game room collection type to an array, it works fine:
IGameRoom[] gameRoomArray = model.AllGameRooms.ToArray();
Contract.Assume(Contract.ForAll(gameRoomArray, g => g != null));
foreach (IGameRoom gameRoom in gameRoomArray)
SetupListeners(gameRoom);//<= NO WARNING
Is this caused by the fact, that you cannot define a rule for methods of the IEnumerable<T> interface?
EDIT3: Can the problem somehow be related to this question?

I think this might have to do with purity of the GetEnumerator method. PureAttribute
Contracts only accept methods that are defined as [Pure] (side effect free).
Some extra information Code Contracts, look for purity
Qoute:
Purity
All methods that are called within a
contract must be pure; that is, they
must not update any preexisting state.
A pure method is allowed to modify
objects that have been created after
entry into the pure method.
Code contract tools currently assume
that the following code elements are
pure:
Methods that are marked with the
PureAttribute.
Types that are marked with the
PureAttribute (the attribute applies
to all the type's methods).
Property get accessors.
Operators (static methods whose names
start with "op", and that have one or
two parameters and a non-void return
type).
Any method whose fully qualified name
begins with
"System.Diagnostics.Contracts.Contract",
"System.String", "System.IO.Path", or
"System.Type".
Any invoked delegate, provided that
the delegate type itself is attributed
with the PureAttribute. The delegate
types System.Predicate and
System.Comparison are considered
pure.

I suspect it's because model.AllGameRooms returns an IEnumerable<GameRoom> which could be different on each property access.
Try using:
var gameRooms = mode.AllGameRooms;
Contract.Assume(Contract.ForAll(gameRooms, g => g != null));
foreach (IGameRoom gameRoom in gameRooms)
SetupListeners(gameRoom);

Related

Compare property values with Reflection

I am trying to build the most budget of ORMs.
I have 2 objects, one "item" and one "original", when creating item, i simply save a COPY of it, in a variable called original. The copy is created via an extension i stole from this post https://stackoverflow.com/a/11308879/10647851
So i want to build my update query, very simple i thought.
foreach (PropertyInfo prop in properties) {
var one = prop.GetValue(original, null);
var typeOne = one.GetType();
var two = prop.GetValue(item, null);
var typeTwo = two.GetType();
if(one != two) { ... }
}
However, one is unequal to two in several cases where you would not expect it.
The ID (type in the model = int?) 2703 is unequal to 2703. I stepped through the code and the type is Int32. Booleans are problems too. Strings work. DateTime?'s work.
Use
if(!object.Equals(one, two)) { ... }
for equality comparison instead. That will invoke the default equality comparator or the overridden one for those types that have implemented it (which includes all value types like int on your example).
!= uses reference equality and therefore produces the same value when the referenced types are exactly the same instance. Using != will give you unexpected results due to the fact you are using GetValue which returns an object.
public object GetValue(object obj)
because one and two are actually reference types (i.e. they are boxed ints instead of value types) the "==" comparator performs a reference equality check.

Incorrect Code Contracts Warnings

I have recently added code contracts to a very large project. After working my way through a few hundred warnings adding assertions to pacify the checker I am left with some warnings which appear to be obviously incorrect! This probably the most simple example I can make (full code is here, if you think the details may be important):
protected Thing DoStuff(A a)
{
Contract.Requires(a != null);
//CodeContracts: Consider adding the postcondition Contract.Ensures(Contract.Result<Thing>() == null); to provide extra-documentation to the library clients
D outResult;
var result = DoSomething(a, out outResult);
if (result == null)
return null;
return new Thing(outResult, result);
}
This suggestion is quite clearly wrong (I have unit tests which return non-null values from this function to prove it)! The only way it could be true is if "DoSomething" also always returns null, but it is not making any suggestion regarding that.
Edit: I have fixed the above problem by totally rewriting the DoSomething method to not use an out result (instead it returns tuple containing both outResult and result). However I still have other false warnings which I would like to solve and probably have the same root cause.
So really this is two questions:
Am I doing something wrong or missing something obvious here?
Assuming CC is simply wrong is there anything I can do to mitigate this kind of problem in the future - at the very least hide the warning!
Re : Contract.Ensures on the return value
In both your MVCE and production code, following the 'burden of proof' upstream, the issue will almost certainly be with the called SelectScript extension method (or DoSomething in the MVCE), where the static analyzer has inferred (possibly incorrectly) that the extension method always returns null, and hence that in the calling method SelectSingle that the first branch (also returning null) would always be chosen, hence the recommended postcondition for null.
I can't find your code for SelectScript, but on VS 2013 update 4 / CC 1.7.11202.10, I can only repeat the Contracts warning by explicitly returning only null from SelectScript and enabling the "Infer ensures" static checking option, OR by explicitly adding a Contract.Ensures(Contract.Result<ScriptReference>() == null); to SelectScript, e.g. with ensures inference on:
public static ScriptReference SelectScript(
this IEnumerable<KeyValuePair<float, KeyValuePair<string, string>[]>> tags,
Func<double> random,
Func<KeyValuePair<string, string>[], Type[], ScriptReference> finder,
out KeyValuePair<string, string>[] selectedTags,
Type t)
{
selectedTags = null;
return null;
}
Produces the same warning in the calling method SelectSingle:
CodeContracts: Consider adding the postcondition Contract.Ensures(Contract.Result() == null); to provide extra-documentation to the library clients
However, for me, the analyzer does appear to correctly infer that the below code has branches which both return null, and non-null, and doesn't recommend the precondition in the caller:
public static ScriptReference SelectScript(
this IEnumerable<KeyValuePair<float, KeyValuePair<string, string>[]>> tags,
Func<double> random,
Func<KeyValuePair<string, string>[], Type[], ScriptReference> finder,
out KeyValuePair<string, string>[] selectedTags,
Type t)
{
Contract.Requires(random != null);
selectedTags = null;
return (random() > 0.5)
? null
: new ScriptReference();
}
Re : Contract.Ensures on the out value
Out of interest, it is also possible to add contracts to out parameters, by using Contract.ValueAtReturn -
reference, section 2.2.3 p8.
e.g. If you are still receiving the warning on the out parameter, you could use grek40's idea to suppress the warnings in the caller by adding this to SelectScript:
Contract.Ensures(Contract.ValueAtReturn(out selectedTags) == null ||
Contract.ValueAtReturn(out selectedTags) != null);

Comparing the value of a property in two instances

I think I'm having boxing issues
foreach(var p in item.GetType().GetProperties().
Where(p => p.GetValue(original, null) is ValueType))
{
var originalValue = p.GetValue(original, null);
var modifiedValue = p.GetValue(item, null);
if (!originalValue.Equals(modifiedValue))
kvpData.AppendFormat("{0}={1}&", p.Name, originalValue);
}
originalValue is never equal to modifiedValue, Im guessing it's because they are boxed inside Object. But how do I fix it?
It is not a boxing issue. Equals is a virtual method, which the boxed value types override just fine.
However, I am not sure what the issue is. Could it be that there aren’t actually any matching properties? Remember that GetProperties() without any parameters will only return public properties. If the properties you need are private, you need to add some BindingFlags:
GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
(I’m assuming here that you don’t want static properties.)
Are you also sure that it is actually properties that you are after and not fields? Remember that if you declare something as
public string Name;
then it’s a field, whereas
public string Name { get; set; }
is a property. If it’s actually fields you need, you need to use GetFields() instead of GetProperties() with the same binding flags.
Linq is a great tool, but I'm not sure why you're using it here. You're actually causing the set of properties to get iterated twice, which is very expensive. I'd write the code without Linq. Also, there's no need to get the value more than once, which is again very expensive. Give this code a try. It avoids the flaws I pointed out and was comparing correctly when I made and tested a dummy class with it:
foreach(PropertyInfo p in item.GetType().GetProperties())
{
if (p.PropertyType.BaseType == typeof(ValueType) || p.PropertyType == typeof(string))
{
var originalValue = p.GetValue(original, null);
var modifiedValue = p.GetValue(item, null);
if (originalValue != modifiedValue) kvpData.AppendFormat("{0}={1}&", p.Name, originalValue);
}
}
Also, note that strings are not a ValueType although they do implement a value comparison.
From MSDN: Object.Equals :
The default implementation of Equals supports reference equality for
reference types, and bitwise equality for value types. Reference
equality means the object references that are compared refer to the
same object. Bitwise equality means the objects that are compared have
the same binary representation.
That means that in your case this 2 objects (if they are reference types) are never point to the same instance.
There is no an easy way to resolve this in so generic way as you would like to do.
But you can implement (just an example) an IComparable on those types you gonna to compare, and after in this iteration check if the type of the value rturned implements that interface, so cast and call it's implemented IComparable.CompareTo method.
You can check if the object implements specified interfacce, in this current case IComparable, you can do something like this:
originalValue .GetType().GetInterfaces().Any(x =>
x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IComparable))
Hope this helps.

Build an object from another object in C# using generic code

Let's say I have an object of Type User that looks like this:
User {
Name = "Bob",
Email = "Bob#gmail.com",
Class = NULL
}
Can anyone think of a way to take that object and create an object like this:
User {
Name = "Bob",
Email = "Bob#gmail.com"
}
Using entirely generic code? Meaning, I don't want to hard code anything to do with the Type, or the Properties because this code would need to be applied to every Entity on my site. (the "User" type is an Entity by the way, so use that if it helps you code this better).
I'm just trying to come up with a solution to a problem I have and I BELIEVE that Stub Entities may fix the problem, but I need to do it without hard coding any Types or Properties.
Use reflection to achieve this:
public void CopyValues<TSource, TTarget>(TSource source, TTarget target)
{
var sourceProperties = typeof(TSource).GetProperties().Where(p => p.CanRead);
foreach (var property in sourceProperties)
{
var targetProperty = typeof(TTarget).GetProperty(property.Name);
if (targetProperty != null && targetProperty.CanWrite && targetProperty.PropertyType.IsAssignableFrom(property.PropertyType))
{
var value = property.GetValue(source, null);
targetProperty.SetValue(target, value, null);
}
}
}
Generics are not gonna help you for this case. There might be some option in the Entity Framework but i am not really known with that.
It would however be possible using Reflection. You could try something like this:
public static void CopyProperties(object a, object b)
{
if (a.GetType() != b.GetType())
throw new ArgumentException("Types of object a and b should be the same", "b")
foreach (PropertyInfo property in a.GetType().GetProperties())
{
if (!property.CanRead || !property.CanWrite || (property.GetIndexParameters().Length > 0))
continue;
property.SetValue(b, property.GetValue(a, null), null);
}
}
Keep in mind tough that this requires all the properties you want to copy to have both a public setter and getter. Also there is the difference between "deep copy" vs "shallow copy" wich means if sub-objects are also copied or only referenced. This example will only reference them so it would be a "shallow copy"
This looks like a problem for reflection rather than generics (although generics can be used as a sneaky way of caching the strategy for reflection). Unless I misread it, you want to create a new instance and copy most of the members... Which reflection is good at, albeit relatively slow. You can improve the speed by using meta-programming; on the first run (per-type) generate an optimised version, perhaps using DynamicMethod or Expression, and store a typed delegate from that. Then just use the delegate.

Code Contracts warning about possibly failing 'Assume' call

In a class of mine, I have a private field of type ExpandoObject. The field is initialized in the constructior (this.expected = new ExpandoObject()), so I'm confident that it will never be null.
Thus, in one of the methods on this class, I fell safe to add
Contract.Assumes(this.expected != null)
before using this.expected for anything, so Code Contracts won't have to worry about possible calls on null objects. However, instead of a warning for possible method call on a null reference, I get a warning saying
The dynamically dispatched call to method 'Assume' may fail at runtime because one or more applicable overloads are conditional method
The method signature and the first few lines of code looks like this:
protected void Expect(object values)
{
Contract.Requires<ArgumentNullException>(values != null);
Contract.Assume(this.expected != null);
var exp = (ICollection<KeyValuePair<string, object>>)this.expected;
On the third line, I get a warning for
CodeContracts: Possibly calling a method on a null reference 'OddEnds.Testing.TestBase.o_SiteContainer0.<>p_Site3.Target'
where I assume the odd signature of the null reference is because exp is a dynamic object.
How do I solve these?
I think the best way to solve your problem is to declare that expected is never null as an invariant on the class:
class TheClass {
ExpandoObject expected;
...
[ContractInvariantMethod]
void Invariants()
{
Contract.Invariant(this.expected != null);
}
...
}
When you do this, the static checker will check that expected is not null at the end of your constructor, and then it will know that expected is never null at the start of any other method.
Im thinking following code change will keep compiler happy (if your sure in this cast anyway, but why use expandoobject then.. anyway)
ICollection<KeyValuePair<string, object>> col = this.expected as ICollection<KeyValuePair<string, object>>;
Contract.Assume(col != null);

Categories