我的类(class)有一个私有(private)静态只读字段:
public class MyClass
{
// ISSUE #1 -- requires unproven: path != null
private static readonly DirectoryInfo MyDirectory =
new DirectoryInfo(Settings.Default.MyDirectoryPath);
protected virtual void SomeMethod()
{
if (MyDirectory.Exists)
{
// ISSUE #2 -- requires unproven: !string.IsNullOrEmpty(path)
var catalog = new DirectoryCatalog(MyDirectory.FullName);
}
}
}
对于问题 #1,我使用空合并运算符默认为某个魔术字符串并修复了它,但我不太喜欢该解决方案。我希望有更好的解决方案。
对于问题 #2,我唯一能想到的就是使用 Contract.Assumes,因为如果我尝试使用 Contract.Requires(MyDirectory.Exists || !String.IsNullOrEmpty(MyDirectory.FullName));
它提示可见性(在 protected 方法的要求中使用的私有(private)字段)。
最佳答案
问题 #1 是 Settings.Default.MyDirectoryPath
由 Visual Studio 生成的代码而没有任何属性契约(Contract)的结果。此问题不仅限于空字符串。许多 API 现在的契约(Contract)要求 TimeSpan
为非负值,但直接在 API 中使用设置会生成代码契约(Contract)警告。
解决此问题的一种方法是将设置包装在具有契约的方法中。例如:
String GetMyDirectoryPath() {
Contract.Ensures(Contract.Result<String>() != null);
var myDirectoryPath = Settings.Default.MyDirectoryPath;
Contract.Assume(myDirectoryPath != null);
return myDirectoryPath;
}
请注意 Contract.Assume
是如何真正执行您的设置验证的(代码契约无法验证它,因为它由外部配置文件控制)。如果它是一个预期为非负数的 TimeSpan
,您可以使用 Contract.Assume
进行验证,从而导致 ContractException
或使用您自己的异常的其他方法。
添加这个额外的层有点乏味,但因为设置是在应用程序外部定义的,所以它需要在某个时候进行运行时验证,就像您必须验证交互式用户输入一样。
问题 #2 可能是因为 DirectoryInfo
没有定义任何契约。最简单的方法是使用 Contract.Assume
。这将声明您认为什么是 DirectoryInfo
的预期行为,但仍然会进行运行时检查以确保您的信念是正确的(前提是您将检查保留在代码中).
var path = MyDirectory.FullName;
Contract.Assume(!string.IsNullOrEmpty(path));
var catalog = new DirectoryCatalog(path);
关于c# - 私有(private)静态只读字段上的代码契约(Contract)和失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11100587/