在 Visual Studio 2010 Professional 中对类库使用代码契约(即无静态检查)有多好?
我创建了类库,其中一些被世界各地的其他人使用,现在我开始使用 Visual Studio 2010,我想知道切换到使用代码契约而不是常规的旧方法对我来说是多么好的主意-样式 if 语句。
IE。而不是这个:
if (fileName == null)
throw new ArgumentNullException("fileName");
使用这个:
Contract.Requires(fileName != null);
我问的原因是我知道静态检查器对我来说不可用,所以我对我所做的一些假设有点紧张,编译器无法验证。当下载它的人有静态检查器时,这可能会导致类库无法编译。再加上我什至无法重现该问题,修复起来会很麻烦,而且我认为,如果它看起来甚至无法从类库中编译出来,那么它并不能说明我的类库的质量。盒子。
所以我有几个问题:
- 如果您有权访问静态检查器,默认情况下它是否处于打开状态?或者我需要在类库中打开一个设置(因为我没有静态检查器,所以我不会)
- 我的担心是没有根据的吗?上述场景是一个真正的问题吗?
欢迎任何建议。
编辑:让我澄清一下我的意思。
假设我在一个类中有以下方法:
public void LogToFile(string fileName, string message)
{
Contracts.Requires(fileName != null);
// log to the file here
}
然后我有以下代码:
public void Log(string message)
{
var targetProvider = IoC.Resolve<IFileLogTargetProvider>();
var fileName = targetProvider.GetTargetFileName();
LogToFile(fileName, message);
}
现在,在这里,IoC 启动,解析一些“随机”类,它为我提供了一个文件名。假设对于这个库,我不可能找回一个不会给我非空文件名的类,但是,由于 IoC 调用的性质,静态分析无法验证这一点,因此可能会假设可能的值可能为空。
因此,静态分析可能会得出这样的结论:存在使用 null
参数调用 LogToFile
方法的风险,从而导致构建失败。
我知道我可以在代码中添加假设,说编译器应该将其视为给定我从该方法返回的 fileName
永远不会为空,但如果我没有静态分析器(VS2010 Professional),上面的代码将为我编译,因此我可能会将其作为一个沉睡的错误留给使用 Ultimate 的人来查找。换句话说,不会有编译时警告表明这里可能存在问题,因此我可能会按原样发布该库。
那么这是一个真实的场景和问题吗?
I create class libraries, some which are used by others around the world, and now that I'm starting to use Visual Studio 2010 I'm wondering how good idea it is for me to switch to using code contracts, instead of regular old-style if-statements.
ie. instead of this:
if (fileName == null)
throw new ArgumentNullException("fileName");
use this:
Contract.Requires(fileName != null);
The reason I'm asking is that I know that the static checker is not available to me, so I'm a bit nervous about some assumptions that I make, that the compiler cannot verify. This might lead to the class library not compiling for someone that downloads it, when they have the static checker. This, coupled with the fact that I cannot even reproduce the problem, would make it tiresome to fix, and I would gather that it doesn't speak volumes to the quality of my class library if it seemingly doesn't even compile out of the box.
So I have a few questions:
- Is the static checker on by default if you have access to it? Or is there a setting I need to switch on in the class library (and since I don't have the static checker, I won't)
- Are my fears unwarranted? Is the above scenario a real problem?
Any advice would be welcome.
Edit: Let me clarify what I mean.
Let's say I have the following method in a class:
public void LogToFile(string fileName, string message)
{
Contracts.Requires(fileName != null);
// log to the file here
}
and then I have this code:
public void Log(string message)
{
var targetProvider = IoC.Resolve<IFileLogTargetProvider>();
var fileName = targetProvider.GetTargetFileName();
LogToFile(fileName, message);
}
Now, here, IoC kicks in, resolves some "random" class, that provides me with a filename. Let's say that for this library, there is no possible way that I can get back a class that won't give me a non-null filename, however, due to the nature of the IoC call, the static analysis is unable to verify this, and thus might assume that a possible value could be null.
Hence, the static analysis might conclude that there is a risk of the LogToFile
method being called with a null
argument, and thus fail to build.
I understand that I can add assumptions to the code, saying that the compiler should take it as given that the fileName
I get back from that method will never be null, but if I don't have the static analyzer (VS2010 Professional), the above code would compile for me, and thus I might leave this as a sleeping bug for someone with Ultimate to find. In other words, there would be no compile-time warning that there might be a problem here, so I might release the library as-is.
So is this a real scenario and problem?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
当您的
LogToFile
和Log
方法都是您的库的一部分时,一旦您打开静态检查器。当您向使用静态检查器编译您的代码的其他人提供代码时,当然也会发生这种情况。但是,据我所知,您客户的静态检查器不会验证您所发送的程序集的内部结构。它将根据程序集的公共 API 静态检查自己的代码。所以只要你只发送 DLL,就可以了。当然,对于实际启用了静态检查器的用户来说,发布一个具有非常烦人的 API 的库是有变化的,所以我认为如果您测试了 API 的可用性,建议仅发布包含契约定义的库有或没有静态检查器。
请注意,请将现有的
if (cond) throw ex
调用更改为您已在先前版本中提供的公共 API 调用的Contracts.Requires(cond)
调用。请注意,Requires
方法抛出的异常(如果我没记错的话,是RequiresViolationException
)与您通常抛出的异常(ArgumentException
)不同。在这种情况下,请使用 Contract.Requires 重载。这样你的API接口就保持不变。When both your
LogToFile
andLog
methods are part of your library, it is possible that yourLog
method will not compile, once you turn on the static checker. This of course will also happen when you supply code to others that compile your code using the static checker. However, as far as I know, your client's static checker will not validate the internals of the assembly you ship. It will statically check their own code against the public API of your assembly. So as long as you just ship the DLL, you'd be okay.Of course there is a change of shipping a library that has a very annoying API for users that actually have the static checker enabled, so I think it is advisable to only ship your library with the contract definitions, if you tested the usability of the API both with and without the static checker.
Please be warned about changing the existing
if (cond) throw ex
calls toContracts.Requires(cond)
calls for public API calls that you have already shipped in a previous release. Note that theRequires
method throws a different exception (aRequiresViolationException
if I recall correctly) than what you'd normally throw (aArgumentException
). In that situation, use the Contract.Requires overload. This way your API interface stays unchanged.首先,静态检查器实际上(据我所知)仅在终极/学术版本中可用 - 因此,除非组织中的每个人都使用它,否则如果他们可能违反不变量,则可能不会收到警告。
其次,虽然静态分析令人印象深刻,但它并不总能找到可能导致违反不变量的所有路径。不过,这里的好消息是
Requires
合约在运行时保留 - 它在 IL 转换步骤中进行处理 - 因此检查在两个编译时都存在和运行时。通过这种方式,它相当于(但优于)常规的if()
检查。您可以阅读有关代码协定编译执行的运行时重写的更多信息 在这里,您还可以阅读详细手册在这里。
编辑:根据我从手册中收集到的信息,我怀疑您描述的情况确实有可能。但是,我认为这些将是警告而不是编译错误 - 您可以使用 System.Diagnostics.CodeAnalysis.SuppressMessage() 来抑制它们。拥有静态验证器的代码使用者也可以标记要忽略的特定情况 - 但如果有很多情况,这肯定会很不方便。我将尝试在今天晚些时候找到一些时间来对您的场景进行明确的测试(我目前无法访问静态验证器)。
这里有一个优秀博客,几乎专门致力于代码合约(如果您还没看过)可能有一些您感兴趣的内容。
First, the static checker is really (as I understand it) only available in the ultimate/academic editions - so unless everyone in your organization uses it they may not be warned if they are potentially violating an invariant.
Second, while the static analysis is impressive it cannot always find all paths that may lead to violation of the invariant. However, the good news here is that the
Requires
contract is retained at runtime - it is processed in an IL-transformation step - so the check exists at both compile time and runtime. In this way it is equivalent (but superior) to a regularif()
check.You can read more about the runtime rewriting that code contract compilation performs here, you can also read the detailed manual here.
EDIT: Based on what I can glean from the manual, I suspect the situation you describe is indeed possible. However, I thought that these would be warninings rather than compilation errors - and you can suppress them using
System.Diagnostics.CodeAnalysis.SuppressMessage()
. Consumers of your code who have the static verifier can also mark specific cases to be ignored - but that could certainly be inconvenient if there are a lot of them. I will try to find some time later today to put together a definitive test of your scenario (I don't have access to the static verifier at the moment).There's an excellent blog here that is almost exclusively dedicated to code contracts which (if you haven't yet seen) may have some content that interests you.
不;静态分析器永远不会阻止编译成功(除非它崩溃!)。
静态分析器将就未经证实的前置/后置条件警告您,但不会停止编译。
No; the static analyzer will never prevent compilation from succeeding (unless it crashes!).
The static analyzer will warn you about unproven pre-/post-conditions, but doesn't stop compilation.