1

编辑:警告-我现在意识到以下技术通常被认为是一个坏主意,因为它为了看起来整洁而创建了隐藏的依赖项。


我最近发现您可以使用 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;
  }
}

我确定上面的伪代码中有错误,但你明白我的意思。


编辑:感谢大家的回复。

4

4 回答 4

5

不这样做的原因有两个:

  • 很慢
  • 它创建了一个脆弱的解决方案。

如果你想这样做,你最好使用支持面向方面编程的工具,比如 Castle 的 Dynamic Proxy。

于 2008-11-25T18:16:24.380 回答
4

另一个问题是编译器可能会在优化过程中“内联”您的方法,例如

void MethodA() {
    MethodB();
}

void MethodB() {
   foo();
}

变成:

void MethodA() {
   foo();
}

这显然是一个问题,因为 foo 的直接调用者不再是 MethodB,而是 MethodA。您可以在方法上放置一个属性以防止它被内联:

[MethodImpl( ... NoInline )]

(具体参数记不清了)

-Oisin

于 2008-11-25T18:19:59.553 回答
3

这很糟糕,因为当我调用它时我不知道该函数做了什么。我无法测试该函数,因为我的测试将从不同的函数调用它,这可能会调用不同的行为。

这很糟糕,因为现在在调用函数时我必须遵守一个“不可见的”合同。我不仅必须确保传递了正确的参数,还必须确保当前函数具有正确的名称。如果我将函数调用包装在匿名 lambda 函数中怎么办?突然间我改变了程序的行为,而且我事先没有猜到,所以现在我可以用第二天的时间来调试程序为什么突然神奇地崩溃了。

重载函数会发生什么?你区分它们吗?具有相同名称但在不同类中的函数?具有“特殊”名称的函数,例如构造函数、终结器、运算符或 lambda?

那么当编译器内联函数时呢?

于 2008-11-25T18:46:11.310 回答
1

这对我来说似乎一点也不酷。为什么要在方法本身中使用所有可能的方法来获得所需的状态?这就像依赖注入的反模式。不要去那里。

于 2008-11-25T19:10:42.587 回答