编辑:警告 - 我现在意识到以下技术通常被认为是一个坏主意,因为它为了看起来整洁而创建隐藏的依赖。
我最近发现您可以使用StackTrace来推断有关方法调用者的信息。
这使您可以创建一个看似“酷”的API,您只需调用一个方法而无需将任何显式参数传递给它,该方法可以根据StackTrace计算出该做什么。
这是一件坏事,如果是这样,为什么?
示例:
public class Cache {
public Object CheckCache()
{
Object valueToReturn = null;
string key = GenerateCacheKeyFromMethodPrototype(new StackTrace().GetFrame(1).GetMethod()); //frame 1 contains caller
if(key is in cache) valueToReturn = itemFromCache;
return valueToReturn;
}
}
public class Foo {
private static Cache cache = new Cache();
public Blah MethodFoo(param1, param2...)
{
Blah valueToReturn = cache.CheckCache(); //seems cool!
if(valueToReturn == null)
{
valueToReturn = result of some calculation;
//populate cache
}
return valueToReturn;
}
}
我确定上面的伪代码存在错误,但你得到了我的漂移。
编辑:感谢大家的回复。
答案 0 :(得分:5)
为什么不这样做有两个原因:
如果您想这样做,最好使用支持面向方面编程的工具,例如Castle的动态代理。
答案 1 :(得分:4)
另一个问题是编译器可能会在优化过程中“内联”您的方法,例如
void MethodA() {
MethodB();
}
void MethodB() {
foo();
}
变为:
void MethodA() {
foo();
}
这显然是一个问题,因为foo的直接调用者不再是MethodB,而是MethodA。您可以在方法上放置一个属性,以防止它被内联:
[MethodImpl( ... NoInline )]
(我记不起确切的参数)
-Oisin
答案 2 :(得分:3)
这很糟糕,因为当我调用它时,我无法知道函数的作用。我无法测试该函数,因为我的测试将从不同的函数调用它,这可能会调用不同的行为。
这很糟糕,因为在调用函数时我必须遵守“隐形”合约。我不仅要确保传递正确的参数,还必须确保当前函数具有正确的名称。如果我在匿名lambda函数中包装函数调用怎么办?突然之间我改变了程序的行为,而且没有提前猜到了,所以现在我可以在第二天调试为什么程序突然而且神奇地破坏了。
重载函数会发生什么?你区分它们吗?具有相同名称但在不同类中的函数?具有“特殊”名称的函数,如构造函数,终结函数,运算符或lambdas?
当编译器内联函数时呢?
答案 3 :(得分:1)
这对我来说似乎并不酷。为什么要在方法本身中采用一切可能的方式来获得所需的状态?这就像依赖注入的反模式。不要去那里。