Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

+ string concat operator with a null operand

Tags:

c#

.net

A co-worker showed me a very strange behavior and I'd like to know if someone could explain me why.

A basic constructor with 2 string params:

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

Method is:

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

When this ctor is called within an aspx page with str2 as null, all works fine because if an operand of string concatenation + is null, an empty string is substituted.

But when this ctor is called with str2 as null in a background thread, a NullReferenceException is fired.

The problem was solved by testing str2 != null before using it, but I'd really like to know why the same code sometimes fires an exception, sometimes not!

Here is the stack trace:

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()
like image 305
Sylv21 Avatar asked Jul 25 '13 14:07

Sylv21


People also ask

Can you concatenate a string with null?

Using the String. The String. concat() method is a good choice when we want to concatenate String objects. The empty String returned by the getNonNullString() method gets concatenated to the result, thus ignoring the null objects.

How do you concatenate null values in a string in SQL?

When SET CONCAT_NULL_YIELDS_NULL is ON, concatenating a null value with a string yields a NULL result. For example, SELECT 'abc' + NULL yields NULL . When SET CONCAT_NULL_YIELDS_NULL is OFF, concatenating a null value with a string yields the string itself (the null value is treated as an empty string).

What is string concatenation operator?

The concatenation operators combine two strings to form one string by appending the second string to the right-hand end of the first string. The concatenation might occur with or without an intervening blank.

Which operator is used for text concatenation?

You can use the concatenation operator ( || ) to concatenate two expressions that evaluate to character data types or to numeric data types.


2 Answers

There was an obscure bug in the .NET Framework's implementation of string concatenation, but it only affected concatenations of 4 objects, where one of the objects is non-null and provided an override of ToString that returned null. Clearly that situation isn't the case here.

This situation is most likely caused by one of the following:

  • _vars is null when Method is called
  • Due to a misuse of _vars in a multi-threaded application, the internal state of _vars has been corrupted, resulting in a NullReferenceException when operator [] is used.
like image 95
Sam Harwell Avatar answered Oct 04 '22 17:10

Sam Harwell


The problem lies in the implementation of the Method Object. Since the + Operator implementation interprets a null value as an empty string. The actuall null value never enters the constructor when set in str2. On the Opposite, str1 directly enters as null value and may depending on the implementation cause a null reference exception.

like image 39
Marwie Avatar answered Oct 04 '22 19:10

Marwie