我如何编程方式检测的副作用(编译时或运行时)?(How can I programmatically

2019-09-21 04:20发布

我得为我开始实现缓存的想法:

Memoizing功能 S和存储与函数签名的散列沿返回速度 。 使用PostSharp ,我要检查缓存并返回返回值的水化表示,而不是再次调用该函数。 我想使用属性来控制此行为。

不幸的是,这可能是危险的其他开发商在我的组织,如果他们爱上的性能增益,并开始装饰每一个方法在视线与缓存的属性,包括一些副作用 。 我想踢走一个编译器警告时,记忆化图书馆犯罪嫌疑人,一个功能可能会引起副作用。

我怎样才能知道这些代码可能会引起副作用,使用的CodeDOM或反射?

Answer 1:

这是一个非常困难的问题,无论是在实践上和理论上。 我们正在认真思考的方式来防止或隔离副作用正是您的场景-记忆化, 自动并行化 ,等等-但它是困难的,我们还远从C#一个可行的解决方案。 所以,没有承诺。 (考虑改用Haskell的,如果你真的想消除副作用)。

不幸的是,即使奇迹发生了,你找到了一种方法,以防止副作用的方法记忆化,你仍然有一些的问题。 考虑以下:

1)如果你memoize的一个函数,它本身就是调用一个函数memoized? 这是一个良好的局面是,对不对? 你想成为能够撰写memoized功能。 但是,记忆化有一个副作用:它增加了数据缓存! 所以,你马上有一个元问题:你想驯服的副作用,但只有“坏”的副作用。 你想要的“好”的人鼓励,要防止坏的,这是很难区分它们。

2)你打算怎么办例外? 您可以memoize的该抛出异常的方法? 如果是这样,它总是抛出同样的异常,或每次它抛出一个新的异常? 如果是前者,你打算怎么办呢? 如果是后者,你现在有一个memoized函数有两个不同的调用两种不同的结果,因为两个不同的抛出异常。 异常可以被看作是一个副作用; 这是很难驯服例外。

3)你打算做哪些没有副作用,但仍然是不纯的方式方法呢? 假设你有一个方法GetCurrentTime()。 不具有副作用; 什么是呼叫突变。 但是,这仍然不是一个候选人memoization的,因为任何两个调用都需要产生不同的结果。 你并不需要一个副作用探测器,你需要的纯度检测。

我认为最好的办法是通过教育和代码审查,以解决人类的问题,而不是试图解决难的技术问题。



Answer 2:

简单地说你不能用任何的CodeDOM或反射。

要准确判断的方法是否会产生副作用,你必须了解它正在采取什么行动。 对于.NET那意味着裂化开放IL和以某种方式interperting它。

无论是反射或CodeDom中给你这个能力。

  • CodeDom中是用于产生代码转换成应用程序的方法和只具有非常有限的检查能力。 它本质上是限于通过各种解析enginse理解语言的子集。
  • 思考的力量在于它的检查元数据,而不是底层的IL方法主体的能力。 元数据只能给你一套非常有限的信息,以什么什么,不产生副作用。


Answer 3:

反思本身不会做,因为元数据不具有任何这样的属性。

CodeDom中可能没有强大到足以检查所有的IL指令。

所以,你必须使用反射API,让你得到一个非常低级别的作品byte[]包含每个方法的原始IL,并分析。 所以这是可能的原则,但并不容易。

你必须分析所有的指令和观察他们有什么影响,以及这些影响是否要一些显著范围之外生存(如不修改,他们可以通过返回值或泄漏对象的领域out参数,或不,他们只是修改,保证不可达的方法以外的临时对象?)。

听起来很复杂!



文章来源: How can I programmatically detect side effects (compile time or run time)?