Taking a .NET collection and displaying the items in a human-readable format is something we all ultimately have to tackle in our applications. While we could spit out values uniformly separated by a character, that’s a very uncivilized approach. I’ll go as far as to say that the comma (,) and the use of “and” separates us from the animals. The peak of human evolution is the Oxford Comma, and it’s all been downhill from that moment.
In this short post, we’ll see how to take a .NET collection and transform it into an Oxford Comma sentence using pattern matching.
The Oxford Comma is Life
For those unfamiliar with the Oxford Comma rule, it’s a grammatical rule that says a final comma can be used in a series. For example, consider the following two sentences:
How Harry Reid, a terrorist interrogator and the
singer from Blink-182 took UFOs mainstream.
How Harry Reid, a terrorist interrogator, and the
singer from Blink-182 took UFOs mainstream.
I am visiting California to see my friends, Mickey Mouse and Dr. Dre.
I am visiting California to see my friends, Mickey Mouse, and Dr Dre.
These two sentences’ meanings change entirely due to a well-placed comma.
When displaying values in code, you may want to format it for your users naturally, and picking the Oxford comma is the most natural form.
Let’s see what tests for an Oxford Comma extension might look like.
Oxford Comma Tests and Extension Method
Let’s start with tests to see what use cases we must account for in our test fixture.
using Xunit.Abstractions;
public class OxfordCommaTests
{
private readonly ITestOutputHelper _output;
public OxfordCommaTests(ITestOutputHelper output)
=> _output = output;
[Fact]
public void Zero_Items()
{
Assert.Equal("", Array.Empty<string>().ToOxfordComma());
Assert.Equal("", (null as string[]).ToOxfordComma());
}
[Fact]
public void One_Item()
{
var items = new[] { "Cats" };
var result = items.ToOxfordComma();
_output.WriteLine(result);
Assert.Equal("Cats", result);
}
[Fact]
public void Two_Items()
{
var items = new[] { "Cats", "Dogs" };
var result = items.ToOxfordComma();
_output.WriteLine(result);
Assert.Equal("Cats and Dogs", result);
}
[Fact]
public void Three_Items()
{
var items = new[] { "Cats", "Dogs", "Capybara" };
var result = items.ToOxfordComma();
_output.WriteLine(result);
Assert.Equal("Cats, Dogs, and Capybara", result);
}
}
Our extension method must account for four scenarios when dealing with collections.
- No items
- One item
- Two items
- Three or more items
Let’s see how I implemented this extension method.
public static class EnumerableExtensions
{
public static string ToOxfordComma(this string[]? items)
{
var result = items?.Length switch
{
// three or more items
>=3 => $"{string.Join(", ", items[..^1])}, and {items[^1]}",
// 1 item or 2 items
not null => string.Join(" and ", items),
// null
_ => string.Empty
};
return result;
}
}
I’m using pattern matching here. There are some interesting points for folks unfamiliar with the C# features in this code block:
- I use range operators to pick out the items as necessary.
- I use
string.Join
behavior to handle two use cases. - I use the
_
discard to handle the default case ofnull
.
Pretty cool if you ask me.
Conclusion
There you have it. Using some newer C# features, we can handle the Oxford comma in a few lines of code. So, consider this extension method next time you consider displaying values to your users.
Thanks for reading this post and sharing it with your friends and colleagues. Cheers.