C# Tester-Doer Pattern

If keyword

The tester-doer pattern describes certain methods. These methods first test the input before doing anything with it. We test the tester-doer pattern. We determine whether tester-doer on Dictionary is better than try and catch and exception handling. In some programs the patterns are interchangeable.

Tester-doer pattern timing

If check:  780 ms
Try/catch: 609 ms [faster]

Introduction

Note

First, Microsoft introduces the tester-doer pattern as a solution to exception performance. TryGetValue is an example of the tester-doer pattern. "Consider the Tester-Doer pattern for members that may throw exceptions in common scenarios to avoid performance problems related to exceptions." (Exceptions and Performance, MSDN)

Test for failure

If your method fails frequently, you usually should test for failure to avoid an exception. However, what if your code doesn't fail often? How expensive is a try/catch block that is almost never used, but still present in the method? This section compares code that tests first, and code that assumes a certain case.

Program that uses tester-doer pattern [C#]

using System.Collections.Generic;

class Program
{
    static void Main()
    {
	var d = new Dictionary<string, int>();
	if (!d.ContainsKey("ok"))
	{
	    d.Add("ok", 1);
	}
    }
}

Program that uses try/catch [C#]

using System.Collections.Generic;

class Program
{
    static void Main()
    {
	var d = new Dictionary<string, int>();
	try
	{
	    d.Add("ok", 1);
	}
	catch
	{
	}
    }
}

Figure A: using tester-doer pattern. The first example here uses the tester-doer pattern to handle cases where the key is in the Dictionary. This will always avoid exceptions related to the Dictionary.

Figure B: alternative version. Here we see code that doesn't check for the unlikely case where the key is found. It assumes everything is in its right place and nothing bad will happen.

Results

Note

I found that in this example it is best to write code that assumes success when success is most likely. In other words, you should not test for cases that are very unlikely or exceptional. Leave the really unlikely stuff to exception-handling. Please see the time measurements at the top of this article.

Benchmark details: 4000000 iterations tested were in a loop. Clear() method on Dictionary was called in each iteration. Code samples A and B were used.

Interpretation. It means that exceptions that are not thrown are sometimes cheaper than lots of manual if checks. Note that if your checks are really fast, the difference would be smaller.

Using exceptions. The example that catches the really rare exceptions can use application-wide logging methods to record them and put them in a central place. I often don't write them to disk but just view them while the application is running.

Summary

The C# programming language

We looked at the tester-doer pattern in the C# programming language. Exceptions are critical and can be faster in certain cases than always checking for failure. I would be kept awake at night if my programs couldn't recover from common or uncommon errors.

Exception Handling
.NET