2011-01-28 17 views
8

protected virtual関数を返す条件に依存するBaseClassに再帰関数があります。再帰関数でのStackOverFlowの防止

子クラスがこの関数を間違ってオーバーライドする可能性があり、StackOverFlow例外が発生する可能性があります。最悪のことは、ネットワークの呼び出しが遅いということです。例外はすぐには起こりません(長い間、多くのリソースが無駄になります)。

StackOverFlowを基本クラスの何らかの初期段階でチェックする方法を探しています(多分Reflectionと現在の再帰レベルを使用しています)。

+0

トピックについての議論。 – Robino

答えて

8

あなたは再帰関数に単純な整数「深さ」を渡すと、後続の各呼び出しで、それをインクリメントすることができます。許容された最大深さよりも大きくなると、Exception権がスローされます。例外が発生するまで待つのではなく、恐ろしいStackOverflow例外が発生します。

whileループでは、このような安全メカニズム(インクリメントカウンタ、それが愚かではないことを確認してください)は便利です。小さなエラーによって無限ループが発生し、膨大なCPUを消費することがあります。

多くのユーザー(Webサイトなど)を持つ大規模なシステムでは、結果がウェブページまたはシステムの1人のユーザーをはるかに超えてしまう可能性があるため、ループやwhileループで予防的対策を講じることをお勧めします。それはかなりコードではなく、純粋主義者は間違いなくそれを抑えるだろうが、それは効率的であり、防衛的であり、実用的だ。

+3

どうやら、イアン・マーサーはここに投稿していますか? – Pierreten

+0

'bool RecursiveConditionMethod(ref int depthLevel){depthLevel ++; //(depthLevel> MAX_DEPTH_LEVEL)がループを壊した場合はそれでいいですか? – Xaqron

+3

@Xaqron、私はそのようなref intを使用しません。メソッドが自分自身を呼び出して、メソッド内の深さの最初のものをチェックするときには、深さ+1を渡します。たとえば、ツリー検索では、訪問した全ノードを制限したくないかもしれませんが、ツリーが適切なツリーではないので、ループで止まらないようにすることができます。 –

1

回避策を作成する代わりに問題を解決します。保護された仮想関数を呼び出す再帰的なprivate関数を作成します。

+0

いいえ。戻り条件は実行時まで基底クラスには明示されず、これはそのメソッドをオーバーライドして子クラスによって提供されます。 – Xaqron

+0

?基本クラスは、子クラスオーバーライドされた実装に依存する必要がありますか? – Pierreten

+1

子クラスは、基本クラスを介して多くの作業を共有するプラグインです。子がそれを深く理解する必要がある場合、それは許されますが、コード自体は基本クラスの中にあり、子どもの間で共有されます。 – Xaqron

0

おそらくコールスタックを読んで解析することはできますが、それはできません。

  1. それが行動

代替DEBUGモードでコールスタックの分析を行うことができ、あなたのベースクラス

  • ドキュメントお使いのベースクラスが責任ではない、実行
  • が遅くなりますのみ。コールスタックを取得する方法を見てみましょう。

    using System.Diagnostics; 
    
    [STAThread] 
    public static void Main() 
    { 
        StackTrace stackTrace = new StackTrace();   // get call stack 
        StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames) 
    
        // write call stack method names 
        foreach (StackFrame stackFrame in stackFrames) 
        { 
        Console.WriteLine(stackFrame.GetMethod().Name); // write method name 
        } 
    } 
    

    From this site