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

これを行わない理由は2つあります。

  • 遅い
  • それはもろい解決策を生み出します。

これを実行したい場合は、CastleのDynamicProxyなどのアスペクト指向プログラミングをサポートするツールを使用することをお勧めします。

于 2008-11-25T18:16:24.380 に答える
4

もう1つの問題は、コンパイラが最適化プロセスでメソッドを「インライン化」する可能性があることです。

void MethodA() {
    MethodB();
}

void MethodB() {
   foo();
}

になります:

void MethodA() {
   foo();
}

fooの即時呼び出し元はMethodBではなく、MethodAであるため、これは明らかに問題です。ただし、メソッドがインライン化されないようにするために、メソッドに配置できる属性があります。

[MethodImpl( ... NoInline )]

(正確なパラメータを思い出せません)

-オシーン

于 2008-11-25T18:19:59.553 に答える
3

呼び出したときに関数が何をするかわからないので悪いです。私のテストは別の関数から呼び出すため、別の動作を呼び出す可能性があるため、関数をテストできません。

そして、関数を呼び出すときに従わなければならない「見えない」コントラクトがあるため、これは悪いことです。正しいパラメーターが渡されていることを確認するだけでなく、現在の関数の名前が正しいことも確認する必要があります。関数呼び出しを無名ラムダ関数でラップするとどうなるでしょうか? 突然プログラムの動作を変更しましたが、事前にそれを推測していなかったので、プログラムが突然魔法のように壊れた理由をデバッグするために次の日を費やすことができます。

オーバーロードされた関数はどうなりますか? それらを区別しますか?同じ名前の関数ですが、クラスは異なりますか? コンストラクター、ファイナライザー、演算子、ラムダなどの「特別な」名前を持つ関数?

また、関数がコンパイラによってインライン展開される場合はどうなるでしょうか?

于 2008-11-25T18:46:11.310 に答える
1

それは私にはまったくクールに思えません。メソッド自体に必要な状態を取得するためのあらゆる可能な方法を配置したいのはなぜですか?これは、依存性注入のアンチパターンのようなものです。そこに行かないでください。

于 2008-11-25T19:10:42.587 に答える