契约注解
契约注解允许您为给定的输入定义预期的输出,或者换句话说,定义函数的引用类型和布尔参数与其返回值之间的依赖关系。 契约注解机制允许创建更易于使用且更安全的 API。
您可以通过使用 [ContractAnnotationAttribute] 装饰您的函数来实现契约注解。 如果您想在源代码中实现此功能,请 引用 JetBrains.Annotations 命名空间。 您还可以使用 外部注解 为现有的二进制模块中的函数添加注解。
运作方式
为了快速了解如何以及为什么使用契约注解,请查看下面的示例。
在此示例中,我们使用契约注解属性装饰了函数 调整。 在这种情况下,属性参数的含义是,null 参数总是会产生 null 返回值。 您可以轻松阅读此示例的代码,看到函数确实以这种方式工作,但在实际代码中,这种依赖关系可能并不那么明显。 无论如何,这里的重点是描述函数如何处理输入值的契约注解属性。
当我们使用 'null' 参数调用 调整 函数时,ReSharper 会立即发现并突出显示一系列问题。 首先,它会突出显示带有 null 参数的函数调用,警告此表达式始终为 null。 然后,它会继续跟踪用此表达式初始化的 已调整 变量,现在该变量也为 'null'。 当我们检查 已调整 变量是否不等于 'null' 时,ReSharper 再次警告我们此比较始终为 false。 最后,ReSharper 将 'if' 语句中的代码灰显为不可达代码:

契约注解的语法
使用以下语法为契约注解指定输入输出依赖关系:
输入 可以是:
null/notnull用于引用类型参数true/false用于布尔参数。
输出 可以是
null/notnull/canbenull用于引用类型的返回值true/false用于布尔类型的返回值中止|停止|void|无返回值(可互换)表示函数不会正常返回。 也就是说,它会抛出异常或终止程序执行。
可选的布尔参数 forceFullStates ,默认为 false,允许您为可空性分析强制启用 悲观模式。 也就是说,如果方法返回值未由契约条件定义,ReSharper 将假定它可能为 null。
言论:
如果只有一个参数(请参阅上面的示例),您可以省略
paramName。如果没有参数,您可以同时省略
paramName和输入:[ContractAnnotation("=> halt")] public void TerminationMethod()或者如果函数的输出与输入无关:
[ContractAnnotation("=> halt")] public void TerminationMethod(object data, bool flag)您可以为同一参数添加多个条件:
[ContractAnnotation("input:null => null; input:notnull=>notnull")] public object Transform(object input, bool flag)您可以反转条件,即
input => output等于output <= input:[ContractAnnotation("null <= surname:null")] public string GetName(string surname)您还可以为 'out' 参数指定预期值。 如果您想为同一输入条件同时指定返回值和 'out' 参数,请使用逗号:
[ContractAnnotation("s:null => false,result:null")] public bool TryParse(string s, out object result)
契约条件的验证
如果您在 源代码中使用契约注解装饰函数,ReSharper 会根据函数签名验证契约条件。 如果契约注解不适合函数参数,ReSharper 会显示警告:

如果契约注解不适合返回值,也会发生同样的情况。
