我一直在阅读有关如何在C#中编写函数(即F#)样式的文章,例如,前面提到的递归循环,并且总是返回值/对象的副本,而不是使用new返回相同的变量状态。
例如,我应该注意哪种代码检查?有没有办法判断一个BCL类的方法是否会导致变异?
答案 0 :(得分:5)
工具NDepend可以告诉您哪里有副作用。它还可以自动确保类是不可变的(即对其对象实例没有副作用)或方法是纯的(即在执行方法期间没有副作用。免责声明:我是开发人员之一工具。
简而言之,技巧是定义一个属性,例如MyNamespace.ImmutableAttribute 并标记您希望不可变的类。
[Immutable]class MyImmutableClass {...}
如果类不是不可变的,或者更有可能,如果开发人员有一天修改它并破坏其不变性,那么以下Code Rule over LINQ Query (CQLinq)将突然发出警告:
warnif count > 0
from t in Application.Types
where !t.IsImmutable && t.HasAttribute("MyNamespace.ImmutableAttribute")
select t
另一方面,我写了一篇关于不变性/纯度/副作用和NDepend用法的文章: Immutable Types: Understand Them And Use Them
答案 1 :(得分:2)
这里有两件事可以帮助您找到值发生变化的变量和字段。当然,可变性比这更复杂(例如,这些将无法找到添加到集合的调用),但根据您要查找的内容,它们可能会有所帮助。
让所有字段都只读;那么它们只能从构造函数中设置,之后不会更改。
拿起ReSharper的副本。它扩展了Visual Studio的语法突出显示,并可以选择为mutable local variables设置自定义突出显示。这将让您一目了然地看到当地人是否正在被修改。
答案 2 :(得分:1)
不幸的是,目前在C#中没有简单的方法。如果你很幸运,文档会告诉你,但通常情况并非如此。
使用Reflector检查代码(假设我们正在讨论托管代码)可以揭示当前实现是否有任何副作用,但由于这是一个实现细节,因此不能保证它不会改变在将来,基本上每次更新相关代码时都必须重复验证。
NDepend等工具可以帮助您找出类型之间的依赖关系 - 即您在哪里寻找副作用。
对于您自己的类型,您可以通过确保实例永远不会泄漏对内部的引用来实现不变性。确保复制用于实例化对象的引用类型实例的内容,否则可能会保留对内部状态的引用。
答案 3 :(得分:0)
如果不测试方法,您将无法判断它是否有任何副作用。如果文档提到了方法或函数的任何副作用,那将会很方便,但不幸的是它没有。
请记住,您必须进行一些广泛的测试,以确保不会出现副作用。如果您愿意,您可以随时拆卸组件并阅读副作用代码。