2

我有一个小的实用程序类:

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);
        }
    }
}

这两种方法都按预期工作。

但是,代码合约静态检查器会抛出两个警告:

警告 30 CodeContracts:确保未经证实:!string.IsNullOrEmpty(Contract.Result())

警告 28 CodeContracts:确保未经证实:!object.Equals(Contract.Result(), default(T))

为什么会发出这些警告?将我的方法合同化的正确(最佳?)方法是什么?

4

1 回答 1

1

Contract.Ensures()不能这么严格。

大多数框架方法都没有用契约修饰。您不能确定它StringBuilder.ToString()不会返回空字符串,因为没有关于XmlSerializer.Serialize()将要做什么的信息。反序列化也一样:没有信息可以断言XmlSerializer.Deserialize()不会返回default(T)对象。

正如@TrustMe-ImADoctor 在评论中指出的那样,您可能必须在代码中为该断言添加额外的检查,然后静态分析将看到该案例已处理且不可能。我想您不需要通过更多检查来污染您的代码,对于这种互操作情况,您可以只使用Contract.Assume().

于 2012-06-15T09:42:26.663 回答