2013-07-25 49 views
8

一位同事向我展示了一個非常奇怪的行爲,我想知道是否有人能解釋我爲什麼。+帶有空操作數的字符串concat運算符

2個PARAMS一個基本的構造:

public MyClass(string str1, string str2) 
    { 
     this.s1 = str1; 
     this.s2 = str2; 
     this.s3 = Method(str2 + "._className", str1); 
    } 

方法是:

public string Method(string key, string defaultValue) 
{ 
    List<string> list = _vars[key]; 
    if (list == null) return defaultValue; 
    string res = ""; 
    foreach (string s in list) 
    { 
     if (res != "") res += ","; 
     res += s; 
    } 
    return res; 
} 

當這個構造函數是一個aspx頁面中調用str2null,一切工作正常,因爲如果一個操作數字符串連接+null,空字符串被替換。

但是,當在背景線程中使用str2作爲null調用此ctor時,會觸發NullReferenceException

問題是由使用它之前測試str2 != null解決,但我真的很想知道,爲什麼相同的代碼,有時觸發一個例外,有時不!

這裏是堆棧跟蹤:

Exception: System.NullReferenceException 
Message: Object reference not set to an instance of an object. 
StackTrace: 
at MyClass..ctor(String str1, String str2) 
at AbandonedCartsNotificationJob.NotifyAbandonedCarts() in AbandonedCartsNotificationJobPartial.cs:line 39 
at AbandonedCartsNotificationJob.work() in AbandonedCartsNotificationJob.cs:line 15 
at MyRuntime.JobManager.run() 
at System.Threading.ThreadHelper.ThreadStart_Context(Object state) 
at System.Threading.ExecutionContext.runTryCode(Object userData) 
at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData) 
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) 
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 
at System.Threading.ThreadHelper.ThreadStart() 
+17

我覺得這裏還有別的事情要做。什麼是'this.s2'用於?什麼是堆棧跟蹤?你可以發佈可重複的代碼供我們測試嗎?你在哪裏做空檢查?是在實例化MyClass之前還是在執行Method之前或者在構造函數的開頭? –

+3

您確定您已將問題追蹤到正確的代碼片段嗎? 'Method'做什麼? –

+0

你確定嗎?你在後臺線程中嘗試過相同的組合嗎 –

回答

4

有.NET框架的執行字符串連接的一個不起眼的錯誤,但它不僅影響4名對象,其中的目標之一就是非空提供的ToString的重寫返回null的級聯。很明顯,情況並非如此。

這種情況很有可能是由以下原因造成:

  • _vars爲空時Method
  • 由於對_vars在多線程應用中的誤用,的_vars內部狀態已被破壞,導致NullReferenceException使用運算符[]時。
+0

這確實是_var的一個問題,Method最初並未設計用於多線程模式。 – Sylv21

3

問題在於Method對象的實現。由於+ Operator implementation interprets a null value as an empty string。當在str2中設置時,真實空值從不進入構造函數。在相反的位置,str1直接輸入爲空值,並且可能取決於實現導致空引用異常。

+0

這不是str1導致異常導致我們通過更改來解決問題: this.s3 =方法(str2 +「._className」,str1); in: this.s3 = str2!= null?方法(str2 +「._className」,str1):str1; – Sylv21

+1

@Sylv21可能當'str2'爲'null'時,'str1'也**爲**'null',這意味着您看不到'str1'爲'null',因爲'str2'上的檢查將其停止。你真的試圖調試代碼,並檢查什麼變量爲空? – Default

+0

str1僅用作Method返回的默認值(請參閱編輯的問題)。 – Sylv21