C# – Join strings with a separator, ignoring nulls and empty strings

Normally when you want to join strings using a separator, you’d use string.Join(). However, the problem with string.Join() is it doesn’t ignore nulls or empty strings. Take a look at the following examples:

string.Join(" - ", null, null) //returns " - "

string.Join(" - ", "test", null) //returns "test - "

string.Join(" - ", "test", "") // returns "test - "
Code language: C# (cs)

If you want to filter out nulls and empty strings, you can filter the list of strings yourself and pass it into string.Join(), like this:

string.Join(" - ", listOfStrings.Where(s => !string.IsNullOrEmpty(s)))
Code language: C# (cs)

In the rest of this article, I’ll show code and tests for helper methods that wrap this join/filter call, and will also show a different approach that uses an extension method that only deals with two strings.

JoinFilter() – Join one or more strings, filtering out nulls and empty strings

It’s a good idea to wrap the join/filter code in a helper method. First, you may need to use this functionality in multiple places in your code. Second, it simplifies things for the calling code.

The following helper methods wrap the two most common overloads of string.Join() and filter out nulls and empty strings:

using System.Collections.Generic;
using System.Linq;

public static class StringUtil
{
	public static string JoinFilter(string separator, IEnumerable<string> strings)
	{
		return string.Join(separator, strings.Where(s => !string.IsNullOrEmpty(s)));
	}
	public static string JoinFilter(string separator, params string[] str)
	{
		return string.Join(separator, str?.Where(s => !string.IsNullOrEmpty(s)));
	}
}
Code language: C# (cs)

This specifically filters out nulls and empty strings, but you can customize it to filter out any strings you want. You may be tempted to pass in the filtering function as a parameter, but at that point there is no use wrapping the call. Instead, I would recommend adding methods that specifically filter what you need.

Here are the parameterized unit tests for the two JoinFilter() methods:

[DataRow(null, null, "")]
[DataRow("", "", "")]
[DataRow("A", null, "A")]
[DataRow(null, "A", "A")]
[DataRow("A", "B", "A - B")]
[TestMethod()]
public void TestJoinFilter_WithList(string a, string b, string expectedString)
{
	//act
	var joinedString = StringUtil.JoinFilter(" - ", new List<string>() { a, b });

	//assert
	Assert.AreEqual(expectedString, joinedString);
}

[DataRow(null, null, "")]
[DataRow("", "", "")]
[DataRow("A", null, "A")]
[DataRow(null, "A", "A")]
[DataRow("A", "B", "A - B")]
[TestMethod()]
public void TestJoinFilter_WithStringParams(string startingString, string appendString, string expectedString)
{
	//act
	var appendedString = StringUtil.JoinFilter(" - ", startingString, appendString);

	//assert
	Assert.AreEqual(expectedString, appendedString);
}
Code language: C# (cs)

Append() extension method – Append one string to another with a separator, ignoring nulls and empty strings

In the previous section, notice that FilterJoin(…, params string[]) accepts any number of individual string parameters. It can be used to join two strings. I’ll show an alternative approach using a string extension method that only deals with appending two strings.

The following code appends two strings together with a separator, but only if they are both not null/empty:

public static class StringExtensions
{
	public static string Append(this string appendTo, string appendString, string separator)
	{
		if (string.IsNullOrEmpty(appendString))
		{
			return appendTo ?? "";
		}
		else if (string.IsNullOrEmpty(appendTo))
		{
			return appendString;
		}

		return string.Join(separator, appendTo, appendString);
	}
}
Code language: C# (cs)

Here are the parameterized unit tests for Append():

[DataRow(null, null, "")]
[DataRow("", "", "")]
[DataRow("A", null, "A")]
[DataRow(null, "A", "A")]
[DataRow("A", "B", "A - B")]
[TestMethod()]
public void TestAppend(string startingString, string appendString, string expectedString)
{
	//act
	var appendedString = startingString.Append(appendString, " - ");

	//assert
	Assert.AreEqual(expectedString, appendedString);
}
Code language: C# (cs)

Notice that the test cases are the same as the ones for FilterJoin().