Returning null from a class constructor?!

Just as an exercise, I thought I’d examine common creation patterns in C# and how operator overloading can expand these.

Typically, if the parameters passed into a class constructor are not valid and thus cannot create an instance of itself, an Exception is thrown. ArgumentNullException is most common when a parameter is null and shouldn’t be. Also common are ArgumentExceptions and FormatExceptions, especially when a constructor takes in a string that must abide by a syntax and doesn’t.

public class Expression
{
	public Expression(string pattern)
	{
		if (Expression.IsInvalidPattern(pattern))
		{
			throw new ArgumentException("pattern is invalid");
		}
		
		// Do something
	}
}

Then a try/catch block is used to catch Exceptions when instantiating the type:

Expression expression;
try
{
	expression = new Expression(pattern);
}
catch(ArgumentException)
{
	// Abort
}

An alternative would be to simply indicate that the instantiated class is in an invalid state:

public class Expression
{
	public readonly bool IsInvalid = false;
	
	public Expression(string pattern)
	{
		if (Expression.IsInvalidPattern(pattern))
		{
			this.IsInvalid = true;
			return;
		}
		// Do something
	}
}

The invalid state is readonly so that it can only be set by the constructor, and is then checked for before performing any operations with the new Expression:

Expression expression = new Expression(pattern);

if (expression.IsInvalid)
{
	// Abort
}

The Parse/TryParse pattern is also common. Instead of an Exception, readonly field, or get-only property, a static TryParse method is used that returns true or false, depending on whether the type can be created:

public class Expression
{
	public static bool TryParse(string pattern,
		out Expression expression)
	{
		if (Expression.IsInvalidPattern(pattern))
		{
			expression = null;
			return false;
		}
		
		expression = new Expression(pattern);
		
		return true;
	}
}

TryParse() is then used as in this example:

Expression expression;

if (!Expression.TryParse(pattern, out expression))
{
	// Abort
}

Another pattern which I haven’t seen used allows an invalid object to emulate a null reference. There are better solutions than this, which is why it isn’t used, but by using operator overloading, it can be accomplished nonetheless.

public abstract class Errorable
{
	protected bool isError = false;

	public static bool operator ==(Errorable left, object right)
	{
		if (right == null)
		{
			return left.isError;
		}
		
		return (left.GetHashCode() == right.GetHashCode());
	}

	public static bool operator !=(Errorable left, object right)
	{
		if (right == null)
		{
			return !left.isError;
		}
		
		return (left.GetHashCode() != right.GetHashCode());
	}
} 

public class Expression : Errorable
{
	public Expression(string pattern)
	{
		if (Expression.IsInvalidPattern(pattern))
		{
			base.isError = true;
			return;
		}
		// Do something
    }
} 

An Expression can then be evaluated to test for null, although we know that “expression” really isn’t a null referenced, which is one reason why this pattern is probably a bad idea.

Expression expression = new Expression(pattern);

if (expression == null)
{
	// Abort
}

Lastly, overloading the ! operator allows us to evaluate an object as fasly, which other languages (e.g. JavaScript) do by default:

public abstract class Errorable
{
	protected bool isError = false;

	public static bool operator !(Errorable errorable)
	{
		if (errorable == null || errorable.isError);
	}
}

public class Expression : Errorable
{
	public Expression(string pattern)
	{
		if (Expression.IsInvalidPattern(pattern))
		{
			base.isError = true;
			return;
		}
		// Do something
    }
}

To test an Expression as invalid, the ! operator is used:

Expression expression = new Expression(pattern);

if (!expression)
{
	// Abort
}

The first two patterns are common, and probably why the last two aren’t used. Generally, if there’s already a good, well-established pattern, there’s no reason to try something else. The alternative shown creation patterns were simply an exercise in operator overloading.

kick it on DotNetKicks.com

About these ads

4 Comments »

  1. You can avoid all together.

    Dont do anything in a contructor, except assigning fields from the ctor values.

    And then have methods that throw exceptions, if the local field is null. Your Exceptions would go from type ArgumentNullException to a InvalidOperationException.

    So basically allow for an object to be created in an invalid state, and only fail if the invalid state is used.

  2. Chris O. said

    What if you had to create multiple Lists<> of hundreds or even thousands of Expressions objects very, very frequently? Any exceptions that routinely get thrown could really start to slow things down.

    Trying to “return null”, as I’ve shown, is probably not the way to go about avoiding an ArgumentException.

    A better choice would be using the Expression.TryParse() method when creating all the new Expressions to Add to List. Checking a readonly field or get-only property for indication of an invalid state would of course work too.

    It probably just comes down to preference. Would you rather:

    Expression expression = new Expression(pattern);
    if (expression.IsInvalid)
    	// Abort
    

    or

    Expression expression;
    if (!Expression.TryParse(pattern, out expression))
    	// Abort
    

    or make things unnecessarily confusing by:

    Expression expression = new Expression(pattern);
    if (expression == null)
    	// Abort
    

    …when expression isn’t actually a null reference.

  3. Actually you inspired me to write about exception usage:

    http://morten.lyhr.dk/2008/03/when-to-throw-exception.html

  4. Regena said

    If you live in a region where water is very contaminated, it would be wise to consider another
    solution such as differing filters that you can
    fit around your home (shower filter, faucet filter or even a whole house filtration system which would ensure all of your water is as
    a good as getting it direct from one of natures springs.

    This episode introduces three people who are embracing creative
    solutions to the looming shortage of drinking water – be it
    desalinating the ocean, catching rainwater or cleaning up our rivers.
    Where the pro water filter system experts say, that the
    body was designed to work with water that contains traces of inorganic
    minerals such as calcium, magnesium, and potassium.

RSS feed for comments on this post · TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: