C# – How to use enum flags to pass multiple options as a single parameter

When you need to pass multiple options into a method, normally you would add a bool flag for each parameter, like:

DoStuff(bool prettyPrint, bool useEnumStrings)

Not only is using bool flags a bit of a code smell, but when this list of parameters gets too big, you’ll probably want to refactor by moving the bool flags into an options class, like:

public class Options
{
	public bool PrettyPrint {get;set;}
	public bool UseEnumStrings {get;set;}
	public bool IgnoreNulls  {get;set;}
}

//caller
new Options() { PrettyPrint=true, UseEnumStrings=true };

This is OK, but it’s pretty verbose. The caller has to new up an Options object and set all the flags it wants turned on.

There’s a simpler approach: enum flags.

With enum flags, you accept a single enum parameter, and the caller passes in all the options they want by bitwise ORing them together, like:

DoStuff(JsonOptions options)

//caller
DoStuff(PrettyPrint | JsonOptions.UseEnumStrings)

In this article I’ll show how to create and use enum flags.

1 – Create enum with Flags attribute

There are two things to know to set this up properly:

  • Add the [Flags] attribute to the enum.
  • Set the values to powers of 2.
[Flags]
public enum JsonOptions
{
	None = 0,
	PrettyPrint = 1,
	UseEnumStrings = 2,
	IgnoreNulls = 4,
	CaseInsensitive = 8
}

2 – Accept the enum as a parameter and check which options are set

I have the following class that builds JsonSerializerOptions objects to use with System.Text.Json. It accepts a single JsonOptions enum parameter and then creates the JsonSerializerOptions objects based on which options were passed in.

Use HasFlag() to check if an option is set.

public class JsonOptionsBuilder
{

	private readonly JsonSerializerOptions NONE;

	public JsonOptionsBuilder()
	{
		NONE = new JsonSerializerOptions();
	}

	public JsonSerializerOptions Build(JsonOptions jsonOptions)
	{
		if (jsonOptions == JsonOptions.None)
		{
			return NONE;
		}

		var jsonSerializerOptions = new JsonSerializerOptions()
		{
			IgnoreNullValues = jsonOptions.HasFlag(JsonOptions.IgnoreNulls),
			WriteIndented = jsonOptions.HasFlag(JsonOptions.PrettyPrint),
			PropertyNameCaseInsensitive = jsonOptions.HasFlag(JsonOptions.CaseInsensitive)
		};

		if (jsonOptions.HasFlag(JsonOptions.UseEnumStrings))
		{
			jsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
		}

		return jsonSerializerOptions;
	}
}

3 – Pass in combos of the enum

To pass in combos of the enum, you need to bitwise OR them together (using the | operator).

In the following example, I am passing in options PrettyPrint and UseEnumStrings.

var people = new List<Person>()
{
	new Person()
	{
		FirstName = "Daniel",
		LastName = "Jackson",
		Job = "Archaeologist",
		PetPreference= PetPreference.Dogs
	},
	new Person()
	{
		FirstName = "Samantha",
		LastName = "Carter",
		Job = "Astrophysicist",
		PetPreference= PetPreference.Cats
	}
};

var jsonOptionsBuilder = new JsonOptionsBuilder();

var options = jsonOptionsBuilder.Build(JsonOptions.PrettyPrint | JsonOptions.UseEnumStrings);

var personJson = JsonSerializer.Serialize(people, options);

Console.WriteLine(personJson);

Leave a Comment