Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Alternative to the C# out keyword using Generics, Anonymous methods and Type converters

0.00/5 (No votes)
12 Jul 2006 1  
This article will demonstrate an alternative to the C# out parameter for those times when you need to get a value back from a method plus some additional information. I'll show you how generics and anonymous methods can be used together to help you write cleaner resuable code.

Contents

Introduction

I really don't like the C# out keyword. I don't like its syntax and the fact that it makes method signatures look so weird. Worse than that though is the way it forces consumers of your code to also write the directive and code 'around it'. I can fully appreciate its purpose and why the designers put it into the C# language spec, but I can't help feeling it could have been done in a cleaner / better way. This article will show you how you can do without the out keyword for certain types of methods by using generics, anonymous methods and implicit / explicit type converters.

What Problem Am I Trying to Solve?

It's probably best to show an example of where the out keyword is used.

Microsoft has used the keyword in the framework. One example is in the Int32.TryParse() method. In order to return a value and a bool back to the caller, they resorted to doing this:

int value;
if (Int32.TryParse("123", out value)) {
   //  we have a real integer
}

// or the more natural (but exception prone) way
value = Int32.Parse("123");

Personally, I feel that the last line looks much cleaner, neater, easier to read and more to the point. You are calling a method that returns a value (just like 90% of the .NET Framework methods do) and your variable will be set or an exception is thrown.

If you have a method that should return a bool and a value, then you're stuck with this pattern (and the dreaded out keyword) unless you decide to return a bespoke object from the method which contains both the value and the return result. Writing another class to get around the out keyword isn't ideal. It introduces a class that exists for perhaps a single method and leaves you with the decision of where to put the class. If the out keyword was bad, this is downright awful.

The out keyword lets us return other values to the caller but it doesn't really help them. Let's say that you called the first method which returned a bool value of false. What does this mean? Of course, at a high level it means that the string passed to the method did not parse into an integer - but why exactly did it fail? All we know is that the string isn't valid for some reason.

int value;
if (!Int32.TryParse(txtAge.Value, out value)) {
   //  ok, we failed to parse the input but why????
}

Wouldn't it be nice if you could pass a message back like "the value you supplied was too big" or "the value contained letters" instead of giving the user a catch all message like "sorry that does not compute". Of course, we can do this by throwing an exception, but it's a performance bottleneck and it forces the consumer of your method to write exception handlers (which I suspect is why Microsoft created the TryParse() method instead).

So, we can sum up the problem by specifying what goals our solution should have. It should:

  1. pass back a value to the caller
  2. pass back a bool indicating if the method succeeded or not
  3. if it failed, then it should give a reason why
  4. if it is warranted, then an exception object should be made available to the caller for them to throw if really necessary
  5. finally, the solution should be unobtrusive and shouldn't change the pattern of function calling like the out keyword has

Solution

We can provide a reusable generic solution to this problem by making use of generics, type converters and anonymous methods. If we can return a reusable rich object which allows the consumer to get the value, message or exception and still write code that looks natural, then I think we're on to a winner.

My Result<T> class provides a solution to all of those requirements and is small enough to not cause any memory or performance issues due to the use of generics. Let's take a look at the Result<T> class below:

  /// <summary>
  /// Reusable generic result class which allows a value, exception
  /// or message information to be passed back to a
  /// calling method in one go.
  /// </summary>
  /// <typeparam name="T">The expected return type</typeparam>
  public class Result<T> {

    protected T result = default(T);
    protected string message = string.Empty;
    protected Exception exception = null;
    protected Predicate<T> boolConverter = delegate { return true; };

    public Result(T result) : this(result, string.Empty, null, null) {}
    public Result(T result, Predicate<T> boolConverter) : 
			this(result, string.Empty, null, boolConverter) { }
    public Result(T result, string message) : this(result, message, null, null) { }
    public Result(Exception exception) : this(default(T), 
				string.Empty, exception, null) { }
    public Result(T result, string message, 
			Exception exception, Predicate<T> boolConverter) {
      this.result = result; 
      this.exception = exception;
      if (exception != null && message == string.Empty)
        this.message = exception.Message;
      else
        this.message = message;
      if(boolConverter!= null)
        this.boolConverter= boolConverter;
    }

    public T ActualResult {
      get { return this.result; }
    }

    public string Message {
      get { return this.message; }
    }

    public Exception Exception {
      get { return this.exception; }
    }

    public bool Success {
      get { return CheckForSuccess(this); }
    }

    public static explicit operator bool(Result<T> result) {
      return CheckForSuccess(result);
    }

    static bool CheckForSuccess(Result<T> result) {
      return result.Exception == null && 
              string.IsNullOrEmpty(result.message) && 
              result.boolConverter(result.ActualResult);
    }

    public static implicit operator T(Result<T> result) {
      if (result.Exception != null)
        throw result.Exception;
      if(!result.boolConverter(result.ActualResult))
        throw new Exception("Result failed the boolConverter test 
				and is not guaranteed to be valid");
      return result.ActualResult;
    }
  }

How To Use It

The first thing to notice is that the class takes a generic parameter when you define an instance of it. If we were to write a wrapper around the Int32.TryParse() method, then it would look something like this:

    public Result<int>ParseInt(string sValue) {
      int value;
      if (!Int32.TryParse(sValue, out value)) {
        // more investigation required into why it failed here
        return new Result<int>(new Exception
		("String couldn't be converted to an integer"));
      }
      return new Result<int>(value);
    }

How Does this Work from the Calling Method's Side?

This is where the pattern really kicks in. The consumer can now decide how they want to use your method. There are no less than two ways to call the ParseInt() method.

Method 1 (the 'confident' method): Treat the return result as a normal value:

public void DoSomething(string sValue) {
   // the ParseInt method will throw an exception if the string 
   // wasn't successfully parsed
   int value = ParseInt(sValue);
}

Method 2 (the 'defensive' method): Treat the return result as a result object

public void DoSomething(string sValue) {
  // the ParseInt method will throw an exception 
  // if the string wasn't successfully parsed
  Result<int> value = ParseInt(sValue);
  if((bool)value) {
    // get the int out of the result
    int intValue = value.ActualValue;
  } else {
    // tell everybody why it failed
    MessageBox.Show(value.Message);

    // or you could do this
    // throw value.Exception;
  }
}

Anonymous Methods

Say we wanted to extend the ParseInt() method so that it only returned true for integers that were:

  1. successfully parsed and 
  2. greater than zero?

That's where the anonymous methods kick in. The Result<T> class provides an alternative constructor which allows a delegate to be passed to it. The delegate is then inspected when the type converters are called or when the Success property is inspected.

public Result<int>ParseInt(string sValue) {
  int value;
  if (Int32.TryParse(sValue, out value)) {
    // more investigation required into why it failed here
    return new Result<int>(new Exception("String couldn't be converted to an integer"));
  }
  return new Result<int>(value, 
    delegate(T obj) {
      if (Convert.ToInt32(obj) > 0)
        return true;
      return false;
    };
  );
}

The result is now only valid when the value is greater than zero.

Type Converters

Explicit

The Result<t> class makes use of both implicit and explicit type converters. The class will always explicitly convert to a bool which indicates whether the method succeeded or not. The value returned can be checked by querying the Success property as well as using the explicit conversion.

Result<int> value = ParseInt(sValue);
if((bool)value) { // this invokes the explicit type converter
}

Implicit

Generally speaking, implicit type conversions can be quite dangerous. One object turning into another type of object without your realising it doesn't exactly set your pulse running, but with the Result<t> class, it is a perfect fit. If you want to treat the Result as the native type, then it will attempt to convert it for you automatically. However, if the method returns a failure result, then an exception is thrown at the point where the conversion takes place. This is to prevent you from using a result which is not valid without you realising it.

Result<int> value = ParseInt(sValue);
if(value > 99) { // this invokes the implicit type converter and may throw an exception
}

Extending the Class

It might be beneficial to extend the Result class for particular datatypes. I know that this goes some way against the whole generics idea but in doing so could allow more specialised results to be put in place. For example, if the result is always numeric, then a sub class could be written that extends Result<t> and adds some standard boolean tests such as:

public static Predicate<T> GreaterThanZero {
  get {
    return delegate(T obj) {
      if (Convert.ToInt32(obj) > 0)
        return true;
      return false;
    };
  }
}

Adding these sort of helper methods nicely encapsulates the logic of the class - yet still allows it to be extended.

Summary

I hope that somebody out there finds this simple class useful. I have used the pattern in a number of large projects and it's been extremely useful to me. I'd love to hear from anybody who uses the class and especially those who extend it.

History

  • 13 July, 2006
    • Fixed code typos, thanks to Murat (muysal81@yahoo.com) for pointing them out
    • Small styling fixes
  • 12 July, 2006
    • Initial article

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here