13 September 2011

Fun with enum

If you’ve done any vaguely serious programming with a pre-4 version of the .NET Framework then chances are you’ve had to write an Enum.TryParse() method. You probably wrote something like this:

public static bool TryParse<TEnum>(string value, out TEnum enumValue)
{
 Type enumType = typeof(TEnum);
 if (!enumType.IsEnum) throw new ArgumentException("Type is not an enum.");
 
 enumValue = default(TEnum);
 
 if (Enum.IsDefined(enumType, value))
 {
  enumValue = (TEnum)Enum.Parse(enumType, value);
  return true;
 }
 
 return false;
}

Everything went fine until someone decided to pass in a string representing a value of the underlying type such as “0” at which point Enum.IsDefined() said no even though your enum looked like this:

public enum MyEnum
{
 Zero = 0, One, Two, Three
}

Enum.Parse() will accept “0” just fine but IsDefined() requires the value be of the correct underlying type so in this case you’d need 0 as an integer for it to return true. Doesn't that mean I now need to work out the underlying type and then do the appropriate Parse() method using reflection? Oh dear, looks like our nice generic solution may get rather complicated!

Fear not. Because we know our input type is a string and there are a very limited number of underlying types we can have there’s a handy framework method we can use to sort this out – Convert.ChangeType().

public static bool IsUnderlyingDefined(Type enumType, string value)
{
 if (!enumType.IsEnum) throw new ArgumentException("Type is not an enum.");
 
 Type underlying = Enum.GetUnderlyingType(enumType);
 
 var val = Convert.ChangeType(value, underlying, CultureInfo.InvariantCulture);
  
 return Enum.IsDefined(enumType, val);
}

ChangeType() is effectively selecting the correct Parse method for us and calling it, passing in our string and returning a nice strongly typed underlying value which we can pass into Enum.IsDefined(). So our TryParse now looks like this:

public static bool TryParse<TEnum>(string value, out TEnum enumValue)
{
 Type enumType = typeof(TEnum);
 if (!enumType.IsEnum) throw new ArgumentException("Type is not an enum.");
 
 enumValue = default(TEnum);
 
 if (Enum.IsDefined(enumType, value) || IsUnderlyingDefined(enumType, value))
 {
  enumValue = (TEnum)Enum.Parse(enumType, value);
  return true;
 }
 
 return false;
}

This exercise is somewhat contrived especially now Enum.TryParse is part of .NET 4.0 but the synergy of ChangeType and IsDefined is quite nice and a technique worth pointing out nonetheless.

Links

13 May 2011

Bulk upsert to SQL Server from .NET

or, “How inserting multiple records using an ORM should probably work”

Anyone familiar with .NET ORMs should know that one area they’re lacking in is where it comes to updating or inserting multiple objects at the same time. You end up with many individual UPDATE and INSERT statements being executed on the database which can be very inefficient and often results in developers having to extend the ORM or break out of it completely in order to perform particular operations. An added complication is that, where identities are being used in tables, each INSERT command the ORM performs must immediately be followed by a SELECT SCOPE_IDENTITY() call to retrieve the identity value for the newly inserted row so that the CLR object may be amended.

It’s possible to drastically improve on this by making use of a couple of features already supported in the .NET Framework and SQL Server and I’m hoping that a similar solution will feature in future releases of the major ORMs.

  • The .NET Framework’s SqlBulkCopy class allowing you to take advantage of BULK operations supported by SQL Server.
  • SQL Server temporary tables.
  • SQL Server 2008’s MERGE command which allows upsert operations to be performed on a table and in particular its ability, using the OUTPUT command, to return identities for inserted rows.

The process

The main steps of the process are as follows:

  1. Using ADO.NET create a temporary table in SQL Server whose schema mirrors your source data and whose column types match the types in the target table.
  2. Using SqlBulkCopy populate the temporary table with the source data.
  3. Execute a MERGE command via ADO.NET on the SQL Server which upserts data from the temporary table into the target table, outputting identities.
  4. Read the row set of inserted identities.
  5. Drop the temporary table.

So instead of n INSERT statements to insert n records that’s four SQL commands in all to insert or update n records.

There’s already a blog post on this technique that goes into more detail by Kelias which you can read here. The only part missing from Kelias’ post is the piece utilising the OUTPUT modifier to retrieve the inserted identities from the MERGE command. This is simply an additional line in the merge command e.g.

OUTPUT $action, INSERTED.$IDENTITY

and the small matter of reading those returned identities out of a SqlDataReader.

This is the crucial piece, however, as it is this which allows us to tie the inserted row back to the original CLR “entity” item that formed part of our source data. Updating our CLR object with this identity will allow us to save subsequent changes away as an UPDATE to the now existing database row.

Performance

I did some brief testing to get rough timings of this technique versus individual INSERT calls using a parameterised ADO.NET command. With a variety of numbers and sizes of rows from 100 to 10,000 and with row sizes from 1k to 10k roughly the upsert technique nearly always executed in less than half the time of the individual INSERT statements. For example, 1,000 rows of about 1k each took individual INSERTs an average of just over 500ms versus bulk upsert’s 150ms on my quite old desktop with not very much RAM.

That’s pretty cool considering the upsert could be performing either an INSERT or an UPDATE command in the same number of calls whereas if I were to factor that into the individual SQL statements method it would be a lot of extra commands to try an UPDATE and then check whether any rows had been affected etc.

Github project

I decided to have a go at wrapping the upsert technique up in a library which would automatically generate the SQL necessary for creating the temporary table and running the MERGE. I pushed an initial version of this SqlBulkUpsert project to github which can be found here:
https://github.com/dezfowler/SqlBulkUpsert

Usage would be something like this:

using (var connection = DatabaseHelper.CreateAndOpenConnection())
{
	var targetSchema = SqlTableSchema.LoadFromDatabase(connection, "TestUpsert", "ident");

	var columnMappings = new Dictionary<string, Func<TestDto, object>>
							{
								{"ident", d => d.Ident},
								{"key_part_1", d => d.KeyPart1},
								{"key_part_2", d => d.KeyPart2},
								{"nullable_text", d => d.Text},
								{"nullable_number", d => d.Number},
								{"nullable_datetimeoffset", d => d.Date},
							};

	Action<TestDto, int> identUpdater = (d, i) => d.Ident = i;

	var upserter = new TypedUpserter<TestDto>(targetSchema, columnMappings, identUpdater);

	var items = new List<TestDto>();

	// Populate items with TestDto instances
	
	upserter.Upsert(connection, items);

	// Ident property of TestDto instances updated
}

with TestDto just being a simple class like this:

public class TestDto
{
	public int? Ident { get; set; }
	public string KeyPart1 { get; set; }
	public short KeyPart2 { get; set; }
	public string Text { get; set; }
	public int Number { get; set; }
	public DateTimeOffset Date { get; set; }
}

In this TypedUpserter example we:

  1. define the schema of the target table either in code or by loading it from the database (shown in the example)
  2. define mappings from column names of the target to a lambda retrieving the appropriate property value from the TestDto class
  3. define an action to be called to allow setting the the new identity to a property of the DTO
  4. instantiate the Upserter and call Upsert() with a list of items and a database connection
  5. the identity properties of the TestDto instances will have been updated using the defined action so the CLR objects will now be consistent with the database rows.

Next step

The object model could probably do with some refinement and it needs lots more tests adding but it’s in pretty good shape so next I’m going to look at integrating it into Mark Rendle’s Simple.Data project which should mean that, to my knowledge, it’s the only .NET ORM doing proper bulk loading of multiple records.

26 January 2011

Adding collections to a custom ConfigurationSection

The attributed model for creating custom ConfigurationSection types for use in your app.config or web.config file is quite verbose and examples are hard to come by. Collections in particular are a pain point, there is very little documentation around them and the examples all tend to follow the default add/remove/clear model i.e. that used in <appSettings/>.

Three particular scenarios with collections which caused me problems while doing the same piece of work were:

  • When the items of a collection have a custom name e.g. "item" instead of add/remove/clear
  • When the items of a collection can have different element names representing different actions or subclasses e.g. the  <allow/> and <deny/> elements used with <authorization/>
  • When the items of a collection don’t have an attribute which represents a unique key e.g. not having anything like the key attribute of an <add/> or <remove/> element

This first and last are relatively trivial to fix, the second less so and it took me a bit of digging around in Reflector to work out how to set up something that worked.

Collection items with a custom element name

This scenario can be accomplished as follows.


public class MySpecialConfigurationSection : ConfigurationSection
{
 [ConfigurationProperty("", IsRequired = false, IsKey = false, IsDefaultCollection = true)]
 public ItemCollection Items
 {
  get { return ((ItemCollection) (base["items"])); }
  set { base["items"] = value; }
 }
}

[ConfigurationCollection(typeof(Item), CollectionType = ConfigurationElementCollectionType.BasicMapAlternate)]
public class ItemCollection : ConfigurationElementCollection
{
 internal const string ItemPropertyName = "item";

 public override ConfigurationElementCollectionType CollectionType
 {
  get { return ConfigurationElementCollectionType.BasicMapAlternate; }
 }

 protected override string ElementName
 {
  get { return ItemPropertyName; }
 }

 protected override bool IsElementName(string elementName)
 {
  return (elementName == ItemPropertyName);
 }

 protected override object GetElementKey(ConfigurationElement element)
 {
  return ((Item)element).Value;
 }

 protected override ConfigurationElement CreateNewElement()
 {
  return new Item();
 }

 public override bool IsReadOnly()
 {
  return false;
 }

}

public class Item
{
 [ConfigurationProperty("value")]
 public string Value 
 {
  get { return (string)base["value"]; }
  set { base["value"] = value; }
 }
}

Which will allow us to specify our section like so:


<configSections>
  <section name="mySpecialSection" type="MyNamespace.MySpecialConfigurationSection, MyAssembly"/> 
</configSections>

...

<mySpecialSection>
 <item value="one"/>
 <item value="two"/>
 <item value="three"/>
</mySpecialSection>

First off we have a property representing our collection on our ConfigurationSection or ConfigurationElement whose type derives from ConfigurationElementCollection. This property decorated with a ConfigurationProperty attribute. If the collection should be contained directly within the parent element then set IsDefaultCollection equal to true and leave element name as empty string. If the collection should be contained within a container element specify an element name.

Next, the ConfigurationElementCollection derived type of the property should have a ConfigurationCollection attribute specifying element type and collection type. The collection type specifies the inheritance behaviour when the section appears in web.config files nested deeper in the folder structure for example.

For the collection type itself we do this:

  • Override ElementName to return collection item element  name
  • Override IsElementName to return true when encountering element name
  • Override GetNewElement() to new up an instance of your item type
  • Override GetElementKey(element) to return an object which uniquely identifies the item. This could be a property value, a combination of values as some hash or the element itself

Collection items with varying element name


public class MySpecialConfigurationSection : ConfigurationSection
{
 [ConfigurationProperty("items", IsRequired = false, IsKey = false, IsDefaultCollection = false)]
 public ItemCollection Items
 {
  get { return ((ItemCollection) (base["items"])); }
  set { base["items"] = value; }
 }    
}
    
[ConfigurationCollection(typeof(Item), AddItemName = "apple,orange", CollectionType = ConfigurationElementCollectionType.BasicMapAlternate)]
public class ItemCollection : ConfigurationElementCollection
{
 public override ConfigurationElementCollectionType CollectionType
 {
  get { return ConfigurationElementCollectionType.BasicMapAlternate; }
 }

 protected override string ElementName
 {
  get { return string.Empty; }
 }

 protected override bool IsElementName(string elementName)
 {
  return (elementName == "apple" || elementName == "orange");
 }

 protected override object GetElementKey(ConfigurationElement element)
 {
  return element;
 }

 protected override ConfigurationElement CreateNewElement()
 {
  return new Item();
 }

 protected override ConfigurationElement CreateNewElement(string elementName)
 {
  var item = new Item();
  if (elementName == "apple")
  {
   item.Type = ItemType.Apple;
  }
  else if(elementName == "orange")
  {
   item.Type = ItemType.Orange;
  }
  return item;
 }
 
 public override bool IsReadOnly()
 {
  return false;
 }
}

public class Item
{
 public ItemType Type { get; set; }

 [ConfigurationProperty("value")]
 public string Value 
 {
  get { return (string)base["value"]; }
  set { base["value"] = value; }
 }
}

Which will allow us to specify our section like so:


<configSections>
  <section name="mySpecialSection" type="MyNamespace.MySpecialConfigurationSection, MyAssembly"/> 
</configSections>

...

<mySpecialSection>
 <items>
  <apple value="one"/>
  <apple value="two"/>
  <orange value="one"/>
 </items>
</mySpecialSection>

Notice that here we've specified two collection items with the value "one" which would have resulted in one overwriting the other in the previous example. To get around this, instead of returning the Value property we're returning the element itself as the unique key.

This time our ConfigurationElementCollection derived type's ConfigurationCollection attribute also specifies a comma delimited AddItemName e.g. "allow,deny". We override the methods of the base as follows:

  • Override ElementName to return empty string
  • Override IsElementName to return true when encountering a correct element name
  • Override GetNewElement() to new up an instance of your item type
  • Override GetNewElement(elementName) to new up an instance of the correct item type for particular element name setting relevant properties
  • Override GetElementKey(element) to return an object which uniquely identifies the item. This could be a property value, a combination of values as some hash or the element itself

Caveat

While our varying element names will be readable the object model is read-only. I haven't covered support for writing changes back to the config file here as it involves taking charge of the serialization of the objects so really requires its own blog post.

Links

05 December 2010

Taking my music listening in a new direction

or, Why I'm cancelling my Spotify Premium subscription

Not entirely sure when I started using Spotify but it was probably late 2008 / early 2009 and I've found it to be a revelation of music discovery. I've spent hours just clicking from one artist to another, exploring back catalogues and having a serious listen to full albums in a way that would be quite difficult without already having bought the album or "obtained" it from P2P. Previously, using a combination of Last.fm and Myspace you could get quite close but the Spotify desktop app made the whole experience so much more seamless and enjoyable with full, consistent quality tracks.

I've been a Premium subscriber since 1 Aug 2009 with several factors leading to my decision to pay up. The first being high-bitrate uninterrupted audio; having some decent audio kit at home I wanted to make the most of it. Second was the Spotify for Android app I could use on my HTC Hero which is hands down the most convenient means of getting music on a mobile device. Put tracks in a playlist in the desktop app and they magically appear on the device – brilliant.

So, why am I quitting?

1. Cost

To date that's £169.83 in subscription fees - £9.99 a month for 17 months. I tend to buy CDs for £5 off Amazon so that equates to about 33 CD albums or about 2 albums a month. I’ve listened to a lot more albums than that during the time but I doubt that there would have been more than 33 that I would have considered buying a CD copy of. I’ve never paid for an MP3, I refuse to pay the same price as a CD for a lossy version but I paid for Spotify as the service does offer significantly more especially when you use the mobile apps. I’m just not sure it’s worth £9.99 a month.

2. Quality

Spotify Premium ups the track bitrate from 160kbps to 320kbps. At least that’s the idea, in practice it seems large portions of their library are only available in the lower quality and I doubt that more than 10% of the tracks I’ve listened to recently have been high bitrate. There’s also no visibility on "high quality" tracks in the app so I’m seriously sceptical about whether I’m getting the high-bitrates I’m paying for. The quality is certainly still miles off CD audio and having made a return to CDs recently it’s very noticeable that I’m missing out on audio clarity and have been making do with poor quality audio whilst also paying for the privilege.

3. Nothing to show for it

It’s a bitter pill to swallow but worst of all is the fact that after all the cost I’ve just been renting the music. I don’t get to keep the OGG tracks, I don’t own any of it and, when I cancel, the app on my phone will just stop working.

What service would I be happy with?

I’ve been wondering about the kind of service I’d like to see and that I’d be happy to pay for. Unlimited ad-supported listening of any tracks for discovering new music would be fine. I’d like to be able to buy albums, download them in full CD quality and stream them uninterrupted (no ads) in a reasonable bitrate to other computers  and mobile devices. I’d also like to be able to register CDs I own with the service so those tracks are also available wherever I am.

The roll-your-own solution might be buying CDs, ripping them and paying $9.99 for at 50GB Dropbox to sync up my machines. Apparently the Dropbox for Android app has the ability to stream music and movies straight to the device so maybe that’s an option worth considering.

Lossless

In this day and age of high-def video, broadband internet  and huge hard disks I don’t want to pay for, and there is no necessity for, low bitrate music. It’s rather interesting that the medium with the highest audio quality most widely available is Blu-ray disc in the form of Dolby TrueHD and DTS-HD. With video the soundtrack is more of a supporting role so lossy compression can be forgiven to some extent but with music the audio is the main event, it should be CD quality at least. MP3 was great for portability but it has a lot to answer for in terms of killing our appreciation of high quality audio and therefore the market’s desire to provide us with (and push) a high-definition medium solely for audio.

25 November 2010

Adding a design mode to your MVC app

When developing websites you'll likely have ended up in the situation where you need to make some styling changes to a page that's buried deep within the site. If that page is at the end of a process such as registration or checkout then it can be extremely time consuming entering test data that passes validation in order to navigate to the correct page. Add to that the complexity of maybe needing to log in and also having to do the same thing on multiple browsers and things can get ridiculous. If you’re using the WebForms view engine then you have limited design time capability in Visual Studio but this isn’t satisfactory for ensuring cross-browser compatibility.

What's needed is a dumb version of the site which simply renders the views using a variety of data. Effectively you want to create a load of static pages, each with ViewData, Model etc set up so that they represent a different step in one of the real processes on the site. Using this version you’d be able to get to the correct page straight away, be able to refresh it quickly after making markup or CSS changes and be able to visit the page in all your test browsers. Ideally using this version of the site will require no authentication and it wont have any external dependencies like databases or web services that must be set up or configured.

We can use a set of different controllers to do this, each having some hard coded model data for example:

// A real controller may look like this... 
public class PeopleController : Controller
{
	public ActionResult Index()
	{
		List<Person> people = GetListOfPeopleFromDatabase();
		return View(people);
	}

	private List<Person> GetListOfPeopleFromDatabase()
	{
		// Do some data access
		
		return new List<Person>
			{
				new Person{ Name = "Runtime Person 1" },
				new Person{ Name = "Runtime Person 2" },
				new Person{ Name = "Runtime Person 3" },
			};
	}
}


// And our design time controller like this...
public class PeopleController : Controller
{
	[Description("Empty people list page")]
	public ActionResult EmptyList()
	{
		return View("Index", new List<Person>{});
	}

	[Description("People list page with 5 random people")]
	public ActionResult ListWithFivePeople()
	{
		return View("Index", new List<Person>
			{
				new Person
				{
					Name = "John Smith"
				},
				new Person
				{
					Name = "Betty Davis"
				},
				new Person
				{
					Name = "Steve Jobs"
				},
				new Person
				{
					Name = "Bill Gates"
				},
				new Person
				{
					Name = "John Carmack"
				},
			});
	}
}

This will work best if your model classes or, the data entity classes you're passing on to your views are dumb i.e. they don't try to do any database access when the view renders. If you already have your controllers in a separate assembly then it should be a relatively simple task to swap your design time ones in and use them instead. If however you have the standard MVC setup of controllers, views and models all in the same project and assembly then things are a bit more difficult.

At the very  least we want our design time controllers in a separate folder of our project, away from the real ones. The issue with this is that the default MVC controller factory will find them here anyway. Thankfully we don't need to implement an entire new factory, we can hide them from the default one by simply breaking with the convention it uses to identify them, the easiest way being not naming them "...Controller".

Home page

A nice to have in this "design" mode would be a default page which shows a list of links to all the actions of the design time controllers with descriptions for what each represents. This would be particularly useful when handing the markup and CSS over to a third party to be styled up as it allows them to quickly access each variation of each screen. You'd end up with something like this:

  • Products
    • List products
    • Search products
    • View product
    • Product category
  • Basket
    • Empty
    • Full
    • Saved
  • My Account
    • Addresses
    • Billing details
  • Home
  • Contact us

Variations

In addition to each individual view the design time functionality could also allow for variations of these pages e.g. logged in / logged out  views, special offer views, user customised views etc. Variations could be  defined on an action, a controller or on the whole site and rather than defining the particular data in each of these cases a transform function could be defined which is called before view render. This function could do work along the lines of setting IsAuthenticated booleans for the logged in / logged out case and possibly more complex operations otherwise.

This would allow a wide variety of viewable pages to be created without  needing to specifically define data in all those cases.

Proof of concept

I've put a quick proof of concept up on Github here:
https://github.com/dezfowler/MvcDesignMode

There's the main MvcDesignMode library and an example MVC app based on the standard template site which has few design time controllers named "...Designer" rather than "...Controller". When not in design mode this should prevent them ever being accidentally accessed provided you're using the default controller factory. I have the code to enable design mode in the App_Start of Global.asax.cs and it looks like this:

bool designMode = Convert.ToBoolean(ConfigurationManager.AppSettings["DesignMode"]);
if (designMode)
{
	DesignMode.Activate(typeof(HomeController));
}
else
{
	AreaRegistration.RegisterAllAreas();
	RegisterRoutes(RouteTable.Routes);
}

Here I'm just using a boolean configuration setting in web.config to turn the mode on and off but how you might choose to do it is up to you. If the design mode is activated the standard application startup stuff is skipped mainly because design mode uses a standard set of routes. Any links in your pages built using custom routes wont work correctly but the point of design mode isn't to be able to navigate around the site as normal it is that you can jump straight to a particular page in one click. I’m passing a type in to the Activate method simply to server as a pointer to the assembly where my design time controllers reside.

Once in design mode the design time controller factory hunts down the special controllers ending with "...Designer" and effectively indexes them pulling out action method names and also the text from a Description attribute defined on the methods. Using this index it builds up a special site map listing each controller and its action methods as links.

Conclusion

Have a look at the solution on Github or have a go implementing something similar yourself. On a number of recent projects I could see having a setup like this saving a lot of time and effort not just for styling and markup but probably developing simple JavaScript stuff as well. I'll definitely be using it myself in all my future MVC projects.

18 November 2010

Pretty print hex dump in LINQPad

Was messing around with byte arrays a lot in LINQPad this week and really wanted a pretty hex print of the contents of the array so wrote this:

public static object HexDump(byte[] data)
{
	return data
		.Select((b, i) => new { Byte = b, Index = i })
		.GroupBy(o => o.Index / 16)
		.Select(g => 
			g
			.Aggregate(
				new { Hex = new StringBuilder(), Chars = new StringBuilder() },
				(a, o) => {a.Hex.AppendFormat("{0:X2} ", o.Byte); a.Chars.Append(Convert.ToChar(o.Byte)); return a;},
				a => new { Hex = a.Hex.ToString(), Chars = a.Chars.ToString() }
			)
		)
		.ToList()
		.Dump();
}

You use it like this:

byte[] text = Encoding.UTF8.GetBytes("The quick brown fox jumps over the lazy dog");

HexDump(text);

...and it will produce output akin to:

hexdump

02 October 2010

The Null Object pattern and the Maybe monad

Dmitri Nesteruk’s recent post Chained null checks and the Maybe monad struck a chord with me as I had messed about with something similar for performing a visitor-esque operation. I’ve glanced at a few posts about monads in the past however this is the first time I’ve had a proper look at one of them.

The purpose of the Maybe monad is essentially to remove the need for null reference checking. If you try to perform some function on an object which turns out to be null you might get a null reference exception. If, however, you perform the function on a Maybe then if the object is null the function is never called. It’s particularly useful if you’re performing a long chain of functions on an object, any of which may return null. In these cases when the null is encountered the remainder of the chain is skipped resulting in more robust, better performing code.

The implementations in .NET that I could find vary quite widely:

One aspect shared by most of these implementations, and which was pointed out in the comments of Dmitri’s post, is that they still end up doing all the null checking, it’s just hidden away. They are treating the “nothing” state as a value, effectively just creating a Nullable<T> which wraps reference types and then checking the HasValue at the beginning of each method call. I think a more elegant solution to this is to use the Null Object pattern.

A Null Object is a special inert type derived from our real class or a common base class. Each method is overridden by a version which has no effect. By wrapping any non-null objects we encounter in an instance of our real type and any nulls in an instance of our inert type we can continually call the methods of these types without fear of null reference exceptions occurring. Moreover, once we receive our inert type from one of the method calls we’re calling the methods on that type so we don’t need null checks at the beginning of our methods as the implementations we’re calling will have no effect.

Example

// Simple testing class
class Node
{
	public int Number { get; set; }
	public Node Parent { get; set; }
}


// Arrange
Node node = new Node
{
	Number = 1,
	Parent = new Node
	{
		Number = 2,
		Parent = new Node
		{
			Number = 3
		}
	}
};

// Act
var third = node.Maybe()
	.Apply(n => n.Parent)
	.Apply(n => n.Parent)
	.Return();

// Assert
Assert.IsNotNull(third);
Assert.AreEqual(3, third.Number);

Here we've got a simple test class and object graph and our code is trying to return the grandparent of node. First we use the Maybe extension method to create the Maybe object after this we're calling methods on the Maybe object itself. The Apply method behaves like a Map method and applies the supplied Func to the subject of the Maybe, returning its result as a new Maybe object. The Return then unwraps the Maybe and returns the subject object if there is one. If any of the methods called on the Maybe object fail we'll end up with a null coming back from Return.

Implementation

The basic structure is an abstract Maybe class with two derived classes; ActualMaybe which contains the real implementation and NothingMaybe which is the Null Object type. The implicit operator on Maybe is where any null is handled.

public abstract class Maybe<T> where T : class
{
	public static readonly Maybe<T> Nothing = new NothingMaybe<T>();
 
	public static implicit operator Maybe<T>(T t)
	{
		return t == null ? Nothing : new ActualMaybe<T>(t);
	}
}

class ActualMaybe<T> : Maybe<T> where T : class
{
	readonly T _t;
	public ActualMaybe(T t)
	{
		if (t == null) throw new ArgumentNullException("t");
		_t = t;
	}
}

class NothingMaybe<T> : Maybe<T> where T : class
{

}

The implementation for Apply is as follows:

// Maybe<T> 
public abstract Maybe<TResult> Apply<TResult>(Func<T, TResult> func) where TResult : class;

// ActualMaybe<T>
public override Maybe<TResult> Apply<TResult>(Func<T, TResult> func)
{
	return func(_t);
}

// NothingMaybe<T>
public override Maybe<TResult> Apply<TResult>(Func<T, TResult> func)
{
	return Maybe<TResult>.Nothing;
}

Apply takes the map function func which operates on the type T and returns some other type TResult. Apply itself returns the Maybe of TResult.

The ActualMaybe implementation simply calls func passing _t, which is the contained object, and returns the result of func. There is more going on here though; first _t can't be null because of the check in the ActualMaybe constructor so we don't need a null check, second we return whatever comes out of func but because the method returns a Maybe of TResult the implicit cast takes place and any nul coming out of func is replaced.

The NothingMaybe implementation ignores func altogether and just returns a NothingMaybe of TResult using the static readonly Nothing field on Maybe<T>.

The ActualMaybe implementation of Return returns _t while the NothingMaybe implementation always returns null.

I’ve implemented a couple of other useful methods including Do(Action<T>), If(Predicate<T>), Cast<TResult>() and AsEnumerable() as well as several overloads.

Possibilities

I think this Null Object approach could be combined with the Visitor pattern to achieve some extensibility although I’m not entirely sure how it would work or whether it would even be necessary.

Another possible extension is some kind of Collect method which would allow you to cherry pick particular objects from a graph and then would return an IEnumerable over just those objects at the end.

Code

I’ve put the code up on Github here:
http://github.com/dezfowler/Monads