Combinable enumerations in C# .NET

You’ve probably encountered cases with combined enum values using the pipe character, i.e. the “bitwise or” operator ‘|’:

Size.Large | Size.ExtraLarge

Let’s see an example of how to create such an enum.

The enumeration is decorated with the Flags attribute like in the following example:

Read more of this post

Advertisement

Checking whether an enum value exists by a parse test in C#

Say you have the following ShipmentOption enumeration:

public enum ShipmentOption
{
	Land,
	Sea,
	Air
}

By default each enumeration value will have an integer representation starting with 0. So 0 corresponds to Land, 1 to Sea and 2 to Air. In addition, each enumeration entry can be stringified such as “Land”, “Sea” and “Air”.

The Enum class has a TryParse method that helps you convert the string representation of the enumeration into the actual enumeration value.

Read more of this post

Checking whether an enum value exists by an integer reference in C#

Say you have the following ShipmentOption enumeration:

public enum ShipmentOption
{
	Land,
	Sea,
	Air
}

By default each enumeration value will have an integer representation starting with 0. So 0 corresponds to Land, 1 to Sea and 2 to Air. Imagine that a method accepts the numeric value like this:

public void SendShipment(int numericShipmentType)

Then the incoming numeric parameter could be anything. How can we check whether an integer has a corresponding enumeration value?

The following code will do just that:

public void SendShipment(int numericShipmentType)
{
	if (Enum.IsDefined(typeof(ShipmentOption), numericShipmentType))
	{
		Console.WriteLine("This type is defined: {0}", (ShipmentOption)numericShipmentType);
	}
	else
	{
		throw new InvalidEnumArgumentException("ShipmentOption", numericShipmentType, typeof(ShipmentOption));
	}
}

The InvalidEnumArgumentException class is defined in the System.ComponentModel namespace.

Passing in 2 will result in the following output:

This type is defined: Air

An invalid integer argument will throw an exception:

The value of argument ‘ShipmentOption’ (5) is invalid for Enum type ‘ShipmentOption’.

View all various C# language feature related posts here.

SOLID principles in .NET revisited part 10: concentrating on enumerations resolved

Introduction

In the previous post we built some bad code. We built it like that deliberately to make you aware of how easy it is to misuse enumerations. We ended up with classes that are coupled in a way that if you extend one then you’ll need to extend at least one other.

In this post we’ll refactor the code to make it better.

Objects instead of enumerations

The main point I want to make in this exercise is that building “proper” objects instead of enumerations can make your code base much more flexible. It’s important to note that there are multiple ways to improve the code. I’m only going to present a solution that I think is good. You might come up with a different solution and it may well be just as good or even superior. The main thing is that the components of your code base should be as loosely coupled as possible.

The PerformanceMetricType enumeration and its members will be transformed into an abstract base class and two implementations. The abstract class will have a single “description” parameter so that the Metric type can be described. It will also have an abstract method where the implementing type will have to extract the correct value from the PerformanceSummary object:

public abstract class Metric
{
	private string _description;

	public Metric(String description)
	{
		if (string.IsNullOrEmpty(description)) throw new ArgumentNullException("Metric description");
		_description = description;
	}

	public string Description
	{
		get
		{
			return _description;
		}
	}

	public abstract double ExtractActualValueFrom(PerformanceSummary performanceSummary);
}

Here come the implementations as well. First AverageResponseTimeMetric:

public class AverageResponseTimeMetric : Metric
{
	public AverageResponseTimeMetric() : base("Average response time per page")
	{}

	public override double ExtractActualValueFrom(PerformanceSummary performanceSummary)
	{
		return performanceSummary.AverageResponseTimePerPage;
	}
}

…and second the UrlCallsPassedPerMinuteMetric:

public class UrlCallsPassedPerMinuteMetric : Metric
{
	public UrlCallsPassedPerMinuteMetric() : base("Url calls passed per minute")
	{}

	public override double ExtractActualValueFrom(PerformanceSummary performanceSummary)
	{
		return performanceSummary.TotalPassedCallsPerMinute;
	}
}

We’ll do the same with the EvaluationOperator enumeration. The abstract base class EvaluationOperation also has a description field and a single abstract method. The implementing class will have to determine whether the actual value breaks a certain limit:

public abstract class EvaluationOperation
{		
	private string _description;

	public EvaluationOperation(String description)
	{
		if (string.IsNullOrEmpty(description)) throw new ArgumentNullException("Description");
		_description = description;
	}

	public string Description
	{
		get
		{
			return _description;
		}
	}

	public abstract bool LimitBroken(double limit, double actual);
}

Here’s the GreaterThan implementation of EvaluationOperation:

public class GreaterThan : EvaluationOperation
{
	public GreaterThan() : base ("Greater than")
	{}

	public override bool LimitBroken(double limit, double actual)
	{
		return actual > threshold;
	}
}

…and here comes LessThan:

public class LessThan : EvaluationOperation
{
	public LessThan() : base("Less than")
	{ }

	public override bool LimitBroken(double limit, double actual)
	{
		return actual < threshold;
	}
}

ThresholdEvaluationResult is the same as before:

public class ThresholdEvaluationResult
{
	public bool ThresholdBroken { get; set; }
}

The updated Threshold class looks quite different from what we had before. The enumeration parameters are gone from the constructor and have been replaced by abstract classes. Also, the logic of evaluating whether a threshold is broken has been placed within the Threshold class instead of some specialised “service”:

public class Threshold
{
	private Metric _metric;
	private EvaluationOperation _operation;
	private double _thresholdValue;

	public Threshold(Metric metric, EvaluationOperation operation, double thresholdValue)
	{
		if (metric == null) throw new ArgumentNullException("Metric");
		if (operation == null) throw new ArgumentNullException("Operation");
		_metric = metric;
		_operation = operation;
		_thresholdValue = thresholdValue;
	}

	public ThresholdEvaluationResult Evaluate(PerformanceSummary performanceSummary)
	{
		ThresholdEvaluationResult res = new ThresholdEvaluationResult();
		double actualValue = _metric.ExtractActualValueFrom(performanceSummary);
		bool broken = _operation.LimitBroken(_thresholdValue, actualValue);
		res.ThresholdBroken = broken;
		return res;
	}
}

As you see the Evaluate method calls upon the injected abstract classes in order to determine whether some limit has been broken. The Threshold class knows nothing about the actual implementations. Also, if you need to extend your domain with other Operation types, such as EqualTo, LessThanOrEqualTo or implement new metric types, like CpuUsageMetric, then you can do that in isolation. Other classes in the model won’t need to be updated at all. The Threshold class will happily accept the new implementations without any complaints.

This post concludes our discussion of SOLID in .NET for the time being.

View the list of posts on Architecture and Patterns here.

SOLID principles in .NET revisited part 9: concentrating on enumerations

Introduction

In the previous post we streamlined our demo code so that it adheres to the SOLID principles. You may still spot bits and pieces that violate some design principle. It’s important to remark that in a large enterprise project it’s very difficult to attain 100% SOLID, if that state exists at all. You might be able to spot “deviations” even in the most well-maintained code bases.

In this post we’ll concentrate on enumerations. We saw before in this series how false usage of enums can easily lead to maintainability problems. Enumerations seem to be very popular due to their simplicity and how easily they can be used to create a list of valid values in a certain category.

We’ll first build up a short case study with all types of mistakes with special emphasis on enumerations. We’ll then improve the code in the next post.

Read more of this post

Combinable enumerations in C# .NET: numeric values of large enums

In this post we saw how to build an enumeration that can be combined using the bitwise OR, i.e. | operator:

var frontEndProgrammer = SoftwarePositions.Programmer | SoftwarePositions.FrontEnd;

We saw that enumeration values must be set in powers of two:

Read more of this post

Combinable enumerations in C# .NET

You’ve probably encountered cases with combined enum values using the pipe character, i.e. the “bitwise or” operator ‘|’:

Size.Large | Size.ExtraLarge

Let’s see an example of how to create such an enum.

The enumeration is decorated with the Flags attribute like in the following example:

Read more of this post

Elliot Balynn's Blog

A directory of wonderful thoughts

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

WEB APPLICATION DEVELOPMENT TUTORIALS WITH OPEN-SOURCE PROJECTS

Once Upon a Camayoc

Bite-size insight on Cyber Security for the not too technical.

%d bloggers like this: