Search code examples
c#code-contracts

CodeContract warning


I have a small utility class :

public static class SerializationUtilities
{
    public static string ToXml<T>(T @object)
    {
        Contract.Requires<ArgumentNullException>(@object != null);
        Contract.Requires<ArgumentException>(typeof(T).IsSerializable);
        Contract.Ensures(!string.IsNullOrEmpty(Contract.Result<string>()));

        var xs = new XmlSerializer(typeof(T));
        var result = new StringBuilder();

        using (var sw = new StringWriter(result))
        {
            xs.Serialize(sw, @object);
        }
        return result.ToString();
    }

    public static T FromXml<T>(string xml)
    {
        Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(xml));
        Contract.Ensures(!object.Equals(Contract.Result<T>(), default(T)));

        var xs = new XmlSerializer(typeof(T));
        using (var sr = new StringReader(xml))
        {
            return (T)xs.Deserialize(sr);
        }
    }
}

The two methods are working as expected.

However, the code contract static checker is throwing two warnings :

Warning 30 CodeContracts: ensures unproven: !string.IsNullOrEmpty(Contract.Result())

Warning 28 CodeContracts: ensures unproven: !object.Equals(Contract.Result(), default(T))

Why are these warning emitted ? What is the correct (best?) way to contractualize my methods ?


Solution

  • Your Contract.Ensures() can't be so strict.

    Most of framework methods aren't decorated with contracts. You can't be sure that StringBuilder.ToString() won't return an empty string because there is not information about what XmlSerializer.Serialize() will do. Same for deserializing: no informations to assert that XmlSerializer.Deserialize() won't return a default(T) object.

    As pointed out by @TrustMe-ImADoctor in the comment you may have to add additional checks in your code for that assertion, static analysis will then see that the case is handled and impossible. I guess you do not need to pollute your code with more checks, for this interop cases you may just use Contract.Assume().