Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Behaviour of string.Join

Tags:

string

c#

I'm using string.Join() to concatenate values with delimiters - here is my simplified example using User class:

public class User
{
    public string Name { get; set; }
    public int Age { get; set; }
}

Here are my results:

User uItem = new User() { Age = 10, Name = null };

string item1 = string.Join(";", string.Empty, 1); // returns ";1"  
string item2 = string.Join(";", null, 1); // returns ""        
string item3 = string.Join(";", uItem.Name, uItem.Age, 1); // returns ""
string item4 = string.Join(";", 1, null); //returns "1;"
string item5 = string.Join(";", null, uItem.Age, 1); // throws null exception

First I was surprised that item2 doesn't behave like item1 and determines a "" instead of ";1".

Is there a rule like null is allowed but not at the first item?

My question: why does item3 return "" and item5 throws a exception? The input values are equal.

like image 752
fubo Avatar asked Dec 02 '22 13:12

fubo


2 Answers

Because you are calling different overloads:

string item5 = string.Join(";", null, uItem.Age, 1); // throws null exception

will call

public static string Join(string separator, string[] value, int startIndex, int count);

(try doing a Go to Definition in Visual Studio and see). So you are passing null as the string[] value.

For the

string item2 = string.Join(";", null, 1); // returns ""

there is a remark in the String.Join Method (String, Object[]) page:

If the first element of values is null, the Join(String, Object[]) method does not concatenate the elements in values but instead returns String.Empty. A number of workarounds for this issue are available. The easiest is to assign a value of String.Empty to the first element of the array, as the following example shows

I do think that this (the special handling of the fist element) is quite stupid (even because the String.Concat Method (Object[]) doesn't have it)

Note that the other overload String.Join<T> Method (String, IEnumerable<T>) doesn't have this special handling:

string item2bis = string.Join(";", (IEnumerable<object>)new object[] { null, 1 }); // returns ";1"

If someone is interested, it isn't something random that causes it... There is explicit C# code in the String.Join implementation of Microsoft:

if (values.Length == 0 || values[0] == null)
    return String.Empty;
like image 50
xanatos Avatar answered Dec 09 '22 23:12

xanatos


From the documentation (emphasis mine):

If separator is null or if any element of values other than the first element is null, an empty string (String.Empty) is used instead.

So the different handling of null is by design. Also, as noted by xanatos, using a different overload causes your exception, since it throws an ArgumentNullException if:

value is null

like image 34
Patrick Hofman Avatar answered Dec 09 '22 22:12

Patrick Hofman