如何以编程方式检测副作用(编译时间或运行时间)?

Chr*_*all 1 c# side-effects memoization

我有一个关于缓存的想法,我已经开始实现了:

记忆函数并将返回与Velocity中的函数签名的散列一起存储.使用PostSharp,我想检查缓存并返回返回值的重新水合表示,而不是再次调用该函数.我想使用属性来控制此行为.

不幸的是,这可能是危险的其他开发商在我的组织,如果他们爱上的性能增益,并开始装饰每一个方法在视线与缓存的属性,包括一些副作用.当memoization库怀疑函数可能导致副作用时,我想发出编译器警告.

如何判断代码可能会导致使用CodeDom或Reflection的副作用?

Eri*_*ert 8

无论是在实践中还是在理论上,这都是一个极其困难的问题.我们正在考虑如何防止或隔离副作用以准确地描述您的场景 - 记忆,自动并行化等等 - 但这很困难,而且我们仍然远不是C#的可行解决方案.所以,没有承诺.(如果你真的想要消除副作用,请考虑切换到Haskell.)

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

1)如果你记住一个本身调用memoized函数的函数怎么办?这是一个很好的情况,对吗?您希望能够撰写记忆功能.但是memoization有副作用:它将数据添加到缓存!所以你马上就会遇到一个元问题:你想要驯服副作用,但只是"坏"的副作用.你想要鼓励的"好",你想要阻止的坏的,并且很难区分它们.

2)你对异常做什么?你能记住一个抛出异常的方法吗?如果是这样,它是否总是抛出相同的异常,或者每次都抛出一个新的异常?如果是前者,你打算怎么做?如果是后者,现在你有一个memoized函数,它在两个不同的调用上有两个不同的结果,因为抛出了两个不同的异常.例外可被视为副作用; 很难驯服例外.

3)对于没有副作用但仍然是不纯的方法的方法,你打算做什么?假设您有一个GetCurrentTime()方法.这没有副作用; 呼叫没有变异.但这仍然不是备忘录的候选者,因为任何两个调用都需要产生不同的结果.您不需要副作用检测器,您需要纯度检测器.

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