Interval: Generic Ranges in C#

There is no doubt about it; out of all the programming languages I ever experimented with, C# has offered me the most streamlined positive development experience so far. It is a modern, ever-evolving language, which now that C# and the whole .NET framework is turning to open source, is guaranteed an even greater future. However, some core constructs commonly available in other languages, like intervals which I introduce an implementation of in this post, are missing. E.g., Ruby has had Ranges for quite some time.

A Range represents an interval—a set of values with a beginning and an end.

Straightforward, but due to the lack of support for generic calculations in C#, a hassle to implement. However, as introduced by Marc Gravell, with some runtime compilation trickery involving expression trees, far from out of reach. I’ve had an Interval class within my core library for quite some time, but just now refactored it to also support more complex intervals, e.g. an interval between two DateTime instances, which thus represents a TimeSpan.

Without further ado, an example of what using this looks like in practice.

// Mockup of a GUI element and mouse position.
var timeBar = new { X = 100, Width = 200 };
int mouseX = 180;

// Find out which date on the time bar the mouse is positioned on,
// assuming it represents whole of 2014.
var timeRepresentation = new Interval<int>( timeBar.X, timeBar.X + timeBar.Width );
DateTime start = new DateTime( 2014, 1, 1 );
DateTime end = new DateTime( 2014, 12, 31 );
var thisYear = new Interval<DateTime, TimeSpan>( start, end );
DateTime hoverOver = timeRepresentation.Map( mouseX, thisYear );

// If the user clicks, zoom in to this position.
double zoomLevel = 0.5;
double zoomInAt = thisYear.GetPercentageFor( hoverOver );
Interval<DateTime, TimeSpan> zoomed = thisYear.Scale( zoomLevel, zoomInAt );

// Iterate over the interval, e.g. draw labels.
zoomed.EveryStepOf( TimeSpan.FromDays( 1 ), d => DrawLabel( d ) );

As you might notice, the timeRepresentation interval has just one generic parameter (Interval<int>), whereas thisYear has two (Interval<DateTime, TimeSpan>). The less generic (one type parameter) class is a simple wrapper around the more generic base type which has two type parameters; the first denotes the type used to represent any position within the range, whereas the second type is used to represent differences between these positions. When these types are the same, the simplified wrapper can be used. Likewise, a TimeInterval wrapper can easily be created if you find Interval to be too verbose.

Worth noting here to understand how it works under the covers is the constructor which sets two public static fields used during operations when conversions to double are needed. Arguably, this could be improved by having a factory creating the intervals and using constructor injection instead.

public TimeInterval( DateTime start, bool isStartIncluded, DateTime end, bool isEndIncluded )
	: base( start, isStartIncluded, end, isEndIncluded )
{
	ConvertDoubleToSize = d => new TimeSpan( (long)Math.Round( d ) );
	ConvertSizeToDouble = s => s.Ticks;
}

Once you start incorporating the notion of an interval in your programming arsenal you will be amazed by the opportunities which present themselves where to use them! Some actual examples within my core library:

To get an impression of the full range of currently supported operations, check out the unit tests.

Null Checks for Event Handlers, an Aspect Solution

There is no denying events in C# are a great step forward from more traditional approaches where a lot of boilerplate code needed to be written. I choose C# events over Java’s solution to the Observer pattern any day.

… but, there is one pesky little issue I have with them. By design, it’s really easy to introduce bugs using them. How often have you encountered a NullReferenceException because you didn’t check whether an event handler was null prior to calling it? As a more experienced developer you might choose one out of the following two options.

1. Repeated null checks

Always check whether an event isn’t null prior to calling it. Additionally, you need to copy the event handler to a local variable, otherwise another thread might unsubscribe from the event causing the handler to be null again after you did the null check.

EventHandler handler = SomeEvent;
if ( handler != null )
{
    handler( ... );
}

2. Always subscribe one empty delegate

There might be a small cost of constantly having to call one extra function when the event is raised, but it solves the problem of having to do repeated null checks throughout the code while simultaneously solving the multi-threading issue.

public event EventHandler SomeEvent = delegate {};

The Aspect way

I prefer the second approach, and don’t see any reason why it shouldn’t be used by default, other than a smarter compiler which could take care of this in a ‘cleaner’ manner. That’s why over the weekend I’ve spent some time seeing how PostSharp could help solving this cross-cutting concern. I always love showing off the result prior to explaining how I got there. It’s usage is a one liner.

[assembly: InitializeEventHandlers( AttributeTargetTypes = "Laevo.*" )]
namespace Laevo { ... }

Adding this one attribute prevents you from having to worry about events throughout the entire namespace it applies to.

How does it work?

First of all, you will need PostSharp. That’s not necessarily a bad thing, because if you are fortunate enough to be allowed to use it, or you can simply decide for yourself to buy it, you will greatly appreciate it for more than just this one possible use case.

The InitializeEventHandlersAttribute is called an aspect which is applied on events. However, using a feature of PostSharp called ‘multicasting’, you are able to apply the attribute (MulticastAttribute) on higher level elements, allowing you to choose which one of the lower level elements the aspect should apply to. In the code above, the aspect is applied on an entire assembly, but the aspect knows it should only be applied to events, which is further narrowed down using the AttributeTargetTypes parameter to events within the namespace “Laevo”, and all sub-namespaces. In order to remind the developer that a certain part of his code is enhanced by an aspect, a visualization as follows is visible within Visual Studio.

The code is short enough to paste in its entirety now, but I’ll decompose it in a minute.

[AttributeUsage( AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Event )]
[MulticastAttributeUsage( MulticastTargets.Event, AllowMultiple = false )]
[AspectTypeDependency(
    AspectDependencyAction.Commute,
    typeof( InitializeEventHandlersAttribute ) )]
[Serializable]
public class InitializeEventHandlersAttribute : EventLevelAspect
{
	[NonSerialized]
	Action<object> _addEmptyEventHandler;

	[OnMethodEntryAdvice, MethodPointcut( "SelectConstructors" )]
	public void OnConstructorEntry( MethodExecutionArgs args )
	{
		_addEmptyEventHandler( args.Instance );
	}

	IEnumerable<ConstructorInfo> SelectConstructors( EventInfo target )
	{
		return target.DeclaringType.GetConstructors(
                    BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic );
	}

	public override void RuntimeInitialize( EventInfo eventInfo )
	{
		base.RuntimeInitialize( eventInfo );

		// Construct a suitable empty event handler.
		MethodInfo delegateInfo = DelegateHelper.MethodInfoFromDelegateType(
                    eventInfo.EventHandlerType );
		ParameterExpression[] parameters = delegateInfo.GetParameters().Select( p =>
                    Expression.Parameter( p.ParameterType ) ).ToArray();
		Delegate emptyDelegate = Expression.Lambda(
                    eventInfo.EventHandlerType, Expression.Empty(),
                    "EmptyDelegate", true, parameters ).Compile();

		// Create a delegate which adds the empty handler to an instance.
		_addEmptyEventHandler = instance => eventInfo.AddEventHandler( instance, emptyDelegate );
	}
}

The steps I followed to create this aspect are documented in the PostSharp 2.1 Documentation “Adding Behaviors to Members”.

  1. Create a new class, deriving from the relevant aspect class. Since I am creating an aspect which is applied on events, I used EventLevelAspect.
  2. Choose on which part of the code your aspect will have effect. This is called an ‘advice’. Although my aspect is applied on events, the solution I used is to add an empty event handler to the events by default. This is something which can be done from the constructor. Therefore I had to use an OnMethodEntryAdvice in order to add this code to the beginning of every constructor.
[OnMethodEntryAdvice, MethodPointcut( "SelectConstructors" )]
public void OnConstructorEntry( MethodExecutionArgs args )
{
	_addEmptyEventHandler( args.Instance );
}
  1. Choosing a ‘pointcut’ is required to determine where the code needs to be added. We’ve already established it needs to be added to the start of methods by using OnMethodEntryAdvice, but we haven’t established which methods it needs to be applied to yet. By using a MethodPointcut, this task is delegated to a separate method of which you pass the name. In my case, this method doesn’t do much more than returning all the constructors of the current type.
IEnumerable<ConstructorInfo> SelectConstructors( EventInfo target )
{
	return target.DeclaringType.GetConstructors(
            BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic );
}
  1. We are nearly done, although there is one part of the code I skipped over which is quite interesting nonetheless. The OnMethodEntryAdvice calls the delegate _addEmptyEventHandler(), but where did this come from? Overriding RuntimeInitialize gives you the chance to initialize objects which the advice will require for the specific element the aspect applies to. Using reflection to analyze the passed EventInfo object, a suitable empty event handler can be constructed using Expression Trees. This is required since we don’t have the luxury of using an equivalent to ‘delegate {}’. Finally a simple delegate is created which can add the empty delegate to the event of any given instance.
public override void RuntimeInitialize( EventInfo eventInfo )
{
	base.RuntimeInitialize( eventInfo );

	// Construct a suitable empty event handler.
	MethodInfo delegateInfo = DelegateHelper.MethodInfoFromDelegateType( eventInfo.EventHandlerType );
	ParameterExpression[] parameters = delegateInfo.GetParameters().Select( p => Expression.Parameter( p.ParameterType ) ).ToArray();
	Delegate emptyDelegate
		= Expression.Lambda( eventInfo.EventHandlerType, Expression.Empty(), "EmptyDelegate", true, parameters ).Compile();

	// Create a delegate which adds the empty handler to an instance.
	_addEmptyEventHandler = instance => eventInfo.AddEventHandler( instance, emptyDelegate );
}

… and all that just to eliminate ‘= delegate {}’? Yes, I can be quite stubborn sometimes. 🙂

UPDATE:

This code has since been slightly altered in order to also support events with generic parameters within generic types. Thank you Anupheaus, for reporting this issue! Be sure to check out the latest code on github. A discussion of the problem, and how to work around it can be found in my answer on Stack Overflow.

Creating delegates during reflection with unbound instances

Previously I discussed how to work around the variance limitations of the Delegate.CreateDelegate method. CreateDelegate has quite a few overloads, and acts differently based on the parameters which are passed. It also allows you to create open instance or closed static delegates. Without going into too much detail:

  • Closed delegate: an instance is bound to the delegate along with the method. In practice this means when calling the delegate, it will always operate on the same instance.
  • Open delegate: not bound to a specific target object until invocation time. An instance on which the method should operate is passed as first argument during invocation.

For now, I will only discuss creating open instance delegates. These allow you to invoke an instance method, while passing a first argument, specifying the instance on which it should be invoked.

Divide your programs into methods that perform one identifiable task. Keep all of the operations in a method at the same level of abstraction. – Kent Beck’s Smalltalk Best Practice Patterns

In an attempt to better follow this principle, better known as the Single Level of Abstraction (SLAP) principle, I’ve split up the CreateDelegate method into two helper methods. One to create ‘simple’ delegates, and one to create open instance delegates. Later, an additional third method could be added to create closed static delegates.

By ‘simple’ delegates I mean delegates of which the signature matches that of MethodInfo. More particularly, the method has the same amount of arguments than the delegate.

public static TDelegate CreateDelegate<TDelegate>(
    MethodInfo method,
    object instance = null,
    CreateOptions options = CreateOptions.None )
    where TDelegate : class
{ ... }

By default, this method results in a simple CreateDelegate call. Instead of having to pass the delegate type as an argument a generic approach is used, eliminating the need to cast the returned delegate. When the options argument is set to CreateOptions.Downcasting, this method behaves like the CreateDowncastingDelegate method from my previous post. Downcasts from the delegate argument types and return type to the required types of the method are generated where needed.

The helper method to create open instance delegates looks as follows:

/// <summary>
///   Creates a delegate of a specified type that represents a method
///   which can be executed on an instance passed as parameter.
/// </summary>
/// <typeparam name = "TDelegate">
///   The type for the delegate. This delegate needs at least one (first) type parameter
///   denoting the type of the instance which will be passed.
///   E.g. Action<ExampleObject, object>,
///        where ExampleObject denotes the instance type and object denotes
///        the desired type of the first parameter of the method.
/// </typeparam>
/// <param name = "method">The MethodInfo describing the method of the instance type.</param>
/// <param name = "options">Options which specify what type of delegate should be created.</param>
public static TDelegate CreateOpenInstanceDelegate<TDelegate>(
    MethodInfo method,
    CreateOptions options = CreateOptions.None )
    where TDelegate : class
    { ... }

The comments indicate clearly what TDelegate should look like. Of course, no instance can be passed, clearly specifying it needs to be specified in the delegate type. Furthermore, the passed MethodInfo is required to be an instance method. All these measures are meant to clarify this specific usage of CreateDelegate. Additionally, similar to passing CreateOptions.Downcasting to the other helper method, it allows you to break the variance safety of the ordinary CreateDelegate method.

Both helper functions can be found in DelegateHelper.cs. I also added MethodInfo extension functions to the reflection extensions, resulting in a more concise syntax.

Example usage:

MethodInfo toUpperMethod = typeof( string ).GetMethod( "ToUpper", new Type[] { } );
Func<string, string> toUpper = toUpperMethod.CreateOpenInstanceDelegate<Func<string, string>>();
string upper = toUpper( "test" ); // Will result in "TEST".

Creating delegates during reflection for unknown types

Using reflection, .NET allows you to create delegates based on MethodInfo objects. Calling a delegate is a lot more performant than using Invoke as already discussed by Jon Skeet. His results showed a delegate invocation is 600 times as fast. Plenty of reason to go through the extra effort of creating and caching a delegate. However, in a real world scenario when adding behavior to an existing class by using reflection, you’ll quickly encounter several limitations when using CreateDelegate. This post shows you where, and how to easily work around them.

In my previous article I discussed covariance and contravariance. One of the limitations of CreateDelegate is it only allows you to create delegates according to those rules. This makes perfect sense, but isn’t always desirable in practical use cases.

How would you go about creating a delegate for any method which is attributed with CallThis when the exact type of the argument is unknown? You do know the method’s signature matches Action, and only the correct type will ever be passed to the delegate.

class CallThisAttribute : Attribute { }
class SomeClass
{
    [CallThis]
    public void SomeMethod( AnyType type ) { ... }
}

...

SomeClass instance = new SomeClass();
MethodInfo methodToCall = instance.GetType().GetAttributedMethod( typeof( CallThisAttribute ) );

// The following would work, but during reflection we don't know about AnyType.
Action<AnyType> action
    = Delegate.CreateDelegate( typeof( Action<AnyType> ), instance, methodToCall );

// The following throws an ArgumentException, since the method can only be called with AnyType.
Action<object> unkownArgument
    = Delegate.CreateDelegate( typeof( Action<object> ), instance, methodToCall );

Creating this delegate isn’t impossible. This is how you would go about creating it ordinarily.

SomeClass instance = new SomeClass();
Action<object> unknownArgument = o => instance.SomeMethod( (AnyType)o );
unknownArgument( new AnyType() );  // This works ...
unknownArgument( 10 );  // ... but this will throw an InvalidCastException.

Can this downcast be generated at runtime? Yes, and the easiest approach seems to be by using expression trees. Instead of passing the type of the required delegate to create as an argument, I opted to use a generic approach. Its usage looks as follows:

Action<object> unknownArgument
    = DelegateHelper.CreateDowncastingDelegate<Action<object>>( instance, methodToCall );

Any possible delegate type can be passed. All parameters of the method, and return value are matched with those of the delegate, and casts are created where necessary.

public static TDelegate CreateDowncastingDelegate<TDelegate>( object instance, MethodInfo method )
{
    MethodInfo delegateInfo = MethodInfoFromDelegateType( typeof( TDelegate ) );

    // Create delegate original and converted arguments.
    var delegateTypes = delegateInfo.GetParameters().Select( d => d.ParameterType );
    var methodTypes = method.GetParameters().Select( m => m.ParameterType );
    var delegateArgumentExpressions
        = CreateDelegateArgumentExpressions( delegateTypes, methodTypes );

    // Create method call.
    Expression methodCall = Expression.Call(
        instance == null ? null : Expression.Constant( instance ),
        method,
        delegateArgumentExpressions.ConvertedArguments );

    // Convert return type when necessary.
    Expression convertedMethodCall
        = delegateInfo.ReturnType == method.ReturnType
              ? methodCall
              : Expression.Convert( methodCall, delegateInfo.ReturnType );

    return Expression.Lambda<TDelegate>(
        convertedMethodCall,
        delegateArgumentExpressions.OriginalArguments
        ).Compile();
}

I’m still not entirely satisfied with the name of the method. CreateDowncastingDelegate refers to the fact that downcasts are generated where necessary. Its usage looks more like an upcasted delegate however. If anyone can come up with a better name, be sure to let me know.

The entire source code can be found in the FCL Extension library. In there you can also find another method which will most likely be the subject of my next post.