2012-09-19 56 views
0

異常我得到的堆棧跟蹤是:基類中的泛型:我的Stacktrace是否缺少一行?

/* snip */ 
at SomeSystemMethod() 
at Namespace.Adapters.ListAdapterBase`1.GetObjects(String where) 
at Namespace.Processes.MyProcess.Run() 
/* snip */ 

這似乎這是第二行之後失去了一些東西,因爲ListAdapterBase是抽象的方法GetObjects不是直接調用,而是通過另一種方法子類:

public class ActualStateList : ListAdapterBase<ActualState> 
{ 
    /* snip */ 
    public List<ActualState> GetByUserId(int userId) 
    { 
     return GetObjects(string.Format(
      WHERECLAUSE_BYUSERID, userId)); 
    } 
    /* snip */ 
} 

所以我的第一個問題是,怎麼會這樣,是沒有的ActualStateList.GetByUserId()呼叫或在堆棧跟蹤另一個孩子的類或方法?

其次:Run()方法使用4個子類ListAdapterBase,我可以以某種方式找出發生異常的地方嗎? ListAdapterBase背後的數字是否恰好導致了其中一個子類?

+0

請顯示'Run'方法的相關部分。 –

回答

3

第一個問題:很可能GetByUserId在Release版本中內聯,這就是爲什麼它不會從堆棧跟蹤中丟失。使用Debug版本應該顯示該方法。

第二個問題:從StackTrace中得到的結果,你無法推斷出哪個子類已被使用。數字(`1)是類名稱ListAdapterBase的一部分,並簡單地聲明該類有一個通用參數。

一個想法但是:由於JIT可以內聯GetByUserId你知道某些事情:

  • 的JIT知道在此作爲virtual方法不聯用子類編譯時間。
  • 調用GetObjects獨生子女類是使用
  • 其中GetObjects被稱爲在simple method獨生子女類考生的具體子類考生。

這些問題可能會幫助您找到特定的子類。

添加一個pdb文件可以提供更多幫助,因爲它會顯示拋出異常的Run方法中的行號。添加pdb文件也可以用於發佈版本。

+0

你能再詳細一點嗎?什麼是內聯?它何時發生?如果某些方法不僅僅只有一行,這是否意味着它不能成爲它們,因爲它們不會被內聯?如果我在發佈大會上使用ILSpy或dotPeek這樣的工具,我會看到內聯? – Hinek

+0

@Hinek:內聯在[wikipedia]中解釋(http://en.wikipedia.org/wiki/Inline_expansion)。第一句話總結得非常好:「在計算,內聯擴展或內聯中,是手動或編譯器優化,用被調用者的主體替換函數調用站點」 –

+0

@Hinek:你不會看到內聯因爲它只在JIT編譯器的運行時發生,而不是C#編譯器。 (我相應地解決了我的問題)。 –

0

正如丹尼爾所說,GetByUserId方法似乎已被編譯器內聯,這就是爲什麼你沒有看到它在堆棧跟蹤。

ListAdapterBase之後意味着它是一個帶有一個類型參數的泛型類型,這當然在這裏沒有幫助,因爲所有派生類都有一個類型參數。您將無法從堆棧跟蹤中找到它是哪一個。

相關問題