2013-07-25 15 views
8

Un collaboratore mi ha mostrato un comportamento molto strano e mi piacerebbe sapere se qualcuno potrebbe spiegarmi perché.+ operatore concat stringa con un operando null

Un costruttore di base con 2 params stringa:

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

metodo è:

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; 
} 

Quando questo ctor viene chiamato all'interno di una pagina aspx con str2 come null, tutto funziona benissimo, perché se un operando di concatenazione di stringhe + è null, una stringa vuota viene sostituita.

Tuttavia, quando questo ctor viene chiamato con str2 come null in un thread in background, viene generato un NullReferenceException.

Il problema è stato risolto testando str2 != null prima di utilizzarlo, ma mi piacerebbe davvero sapere perché lo stesso codice genera talvolta un'eccezione, a volte no!

Ecco la traccia dello stack:

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

Mi sento come se qualcos'altro stia succedendo qui. A cosa serve 'this.s2'? Qual è la traccia dello stack? Puoi pubblicare un codice riproducibile con cui testarci? Dove stai facendo il controllo nulla? È prima di istanziare 'MyClass' o prima di eseguire' Method' o all'inizio del costruttore? –

+3

Sei sicuro di aver rintracciato il problema nella parte corretta del codice? Cosa fa 'Method'? –

+0

Sei sicuro? hai provato la stessa combinazione in thread in background? –

risposta

4

C'era un oscuro bug nell'implementazione di .NET Framework di concatenazione di stringhe, ma ha interessato solo concatenazioni di 4 oggetti, in cui uno degli oggetti non è nullo e fornito un override di ToString che restituito null. Chiaramente quella situazione non è il caso qui.

Questa situazione è probabilmente causato da uno dei seguenti:

  • _vars è nullo quando Method è chiamato
  • causa di un uso improprio di _vars in un'applicazione multi-thread, lo stato interno del _vars è stato danneggiato, risultando in un NullReferenceException quando viene utilizzato l'operatore [].
+0

In realtà era un problema con _var, il metodo non è stato inizialmente progettato per essere utilizzato in modalità multi-thread. – Sylv21

3

Il problema sta nella realizzazione del Method oggetto. Dal momento che il + Operator implementation interprets a null value as an empty string. Il valore null di actuall non entra mai nel costruttore se impostato in str2. Sul lato opposto, str1 immette direttamente come valore nullo e può dipendere dall'implementazione causa un'eccezione di riferimento null.

+0

Non è lo str1 che causa l'eccezione, abbiamo risolto il problema cambiando: this.s3 = Metodo (str2 + "._className", str1); in: this.s3 = str2! = Null? Metodo (str2 + "._className", str1): str1; – Sylv21

+1

@ Sylv21 forse quando 'str2' è' null', 'str1' è ** anche **' null', il che significa che non si vede che 'str1' è' null' perché il controllo su 'str2' lo ha fermato. Hai effettivamente provato a eseguire il debug del codice e controllato quale variabile è nullo? – Default

+0

str1 viene utilizzato solo come valore predefinito restituito dal metodo (vedere la domanda modificata). – Sylv21

Problemi correlati