2016-12-14 3 views
1

Expression.Lambdaを使用してデリゲートをコンパイルしています。StackTraceでコンパイルされたLambdaの最初のメソッドが見つかりません

最近、例外がスローされたときに、ターゲット代理人に焼き付けられた「トップレベル」メソッドがスタックトレースにないことに気付きました。

using System; 
using System.Linq.Expressions; 
using System.Reflection; 

namespace Sandbox 
{ 
    public class Program 
    { 
     private static void Main() 
     { 
      var methodInfo = typeof(X).GetMethod(nameof(X.Method1), BindingFlags.Static | BindingFlags.Public); 
      var call = Expression.Call(methodInfo); 
      var compiledDelegate = Expression.Lambda<Action>(call, null).Compile(); 

      try 
      { 
       compiledDelegate(); 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine(e.ToString()); 
      } 
      Console.ReadKey(); 
     } 

     public class X 
     { 
      public static void Method1() 
      { 
       Method2(); 
      } 

      public static void Method2() 
      { 
       Console.WriteLine("Strange"); 
       throw new Exception(); 
      } 
     } 
    } 
} 

.EXE(releasebuild)方法1が欠落していることを

System.Exception: Eine Ausnahme vom Typ "System.Exception" wurde ausgelöst. 
bei Sandbox.Program.X.Method2() in [..]\Program.cs:Zeile 38. 
bei lambda_method(Closure) 
bei Sandbox.Program.Main() in [..]\Program.cs:Zeile 18. 

お知らせを実行している時には、次のスタックトレースを取得します:

詳細な使用例は、この現象を再現します。

私の質問はここにあります:方法1を表示させるにはどうしたらいいですか?

Method1はインラインになっているようですが、コールスタックから削除する必要がありますか、間違っていますか?

+2

インライン化は、 'Method1'の命令が直接実行されることを意味し、実際にはスタックトレースから削除されます。デバッグモードでの動作は何ですか? – Maarten

+0

デバッグが表示されます。 – CSharpie

+0

Method1に出力行を追加し、何が起こるかを確認してください。 – dasblinkenlight

答えて

0

JIT compilerがメソッド呼び出しをインライン化するほどスマートなので、表示されません。

あなたは、パフォーマンスを少し低下させる可能性がある、それをインライン展開しないようにコンパイラに強制することにより、それを防ぐことができます。

[MethodImpl(MethodImplOptions.NoInlining)] 
public static void Method1() 
{ 
    Method2(); 
} 

コンパイラは簡単なデバッグのためにそれらのアセンブリを最適化していないので、それはすでにデバッグビルドモードで動作します。

+1

明確にするために、「インラインではなくコンパイラを強制的に実行する」と言いますと、C#コンパイラではなく、実行時の(ちょうどその前に)実行時のジッタを参照しています。 –

+0

私はターゲットタイプにアクセスしていないと言って忘れてしまったので、私はおそらくそれと一緒に暮らす必要があります。 @JeppeStigNielsen JITはコンパイラです。 – CSharpie

+0

@JeppeStigNielsenはい、あなたは正しいです。もちろん、Reflectionを使用してメソッドを見つけることができます。そのため、余分なステップはJITterによってただ削除されます。 –

関連する問題