Category Archives: Code

Use Appropriate Collections

.Net makes using fancy collections very easy. In fact, it can be almost too easy. It is so simple to just throw in a List<T> or a ConcurrentDictionary<K, T> that it’s tempting to do it at every opportunity.

Today’s tip is to stop and think critically about the type of collections you need.

Some examples:

  • I was doing a code review recently and saw that this person was using Dictionary<string, bool> where every value was true. This is not a dictionary—it’s a set with complicated accessors. So use HashSet<T> – it has a simpler API, which will lead to your own code being simpler and more correct semantically. Dictionary<K, T> has a meaning, and if you’re abusing that meaning, then your code is likely incorrect, or in the best case, misleading (and thus a maintenance problem, and thus incorrect!).
  • Performance characteristics are often non-intuitive. For example, if you’re doing a lot of searching for values, which would you use? Dictionary<K, T> or List<T>? Most people would say the Dictionary, and perhaps in 95% of cases, they’re right. On the other hand, if you only have a few values, you may get better performance because of cache locality with a binary search over a List (or even a linear search), which is usually implemented as an array.
  • Speaking of arrays, if you have a read-only vector of a known size, use arrays instead of Lists. It’s semantically more correct, simpler, and usually more performant.
  • Another code review I was doing had usage of ConcurrentDictionary<K, T>. This sounds like a great type to use when you need to modify and/or read a dictionary with multiple threads, but the usage of this type is not that straightforward, and in fact the official documentation is unclear on some things. In this case, it was better to redesign at a higher level to avoid use of this type.
  • I’ve seen this type of code in reviews a few times:
var list = new List<MyObject>();
for (int i =0;i < source.Count; ++i)
{
    list.Add(source.Get(i));
}

        In most apps maybe this doesn’t matter. If you care about performance, then you should care that there are going to be an unknown number of pointless memory allocations, plus multiple copies of the old data into the new arrays. In a high-performance system, this matters. Use the constructor of the collection that takes an initial size. (Guess how many items are in the default List<T> internal item array: None.)

Some questions you can ask yourself:

  • Is the collection semantically correct? Or am I abusing it because it can do what I want? Do I have restrictions on the use of the collection that are not obeyed by the API of the collection? Is there a more appropriate data structure I can use? If not, should I wrap this collection into an API with suitable restrictions?
  • Am I using the simplest collection possible?
  • Is this collection type performant for how it will be used? How can I measure to make sure? Am I making assumptions that may be unfounded because of usage patterns or hardware optimizations? Am I initializing the data structure correctly, to avoid unnecessary memory reallocations?
  • Is the collection type I’m considering too complex to use effectively? Would it be better to redesign something at a higher level to avoid needing to use this collection type?

Collections are usually the core of any application (if you don’t have data, what you are acting upon?). Getting these right means simpler code, better performance, higher readability, and long-term maintainability. It doesn’t take any more work (usually) – it just takes a few moments to think about what you’re really doing.

Like this tip? Check out my book, C # 4.0 How-To, where you’ll finds hundreds of great tips like this one.


Check out my latest book, the essential, in-depth guide to performance for all .NET developers:

Writing High-Performance.NET Code, 2nd Edition by Ben Watson. Available for pre-order:

Don’t Log Exception Stacks Unless You Can Afford It

A short, simple tip for this week: Don’t log exception stacks in managed applications unless you understand the performance of your system.

If you have a standard desktop client, or some other app where you can tolerate many-millisecond disruptions or a spike in CPU usage, then you don’t have to care about this.

If you are building a high-performance managed system, then you definitely do have to care about this.

The system I work on needs to handle exceptions coming from 3rd-party components. We can’t let the exceptions kills the process, and we can’t swallow them, ignoring the component failure, so we need to log them. The question is—what information do we log?

For managed exceptions, there are three properties that are most generally useful: type of the exception, Message, and StackTrace.

Getting the type and the Message are nearly free, but accessing StackTrace or calling ToString() on the exception object will cause a bunch of reflection to happen to build up a user-friendly stack trace string. If you can do without, go for it. It may be possible to augment the Message property of an exception to give some clues to the problem. Usually, however, this will not be possible.

Since getting the stack trace for an exception is relatively expensive, especially for a program that shouldn’t miss a beat and needs to continue running, many of the managed applications that I work on have a configuration setting to be able to turn off stack trace logging for exceptions. This enables us to either run it turned on until we see a performance problem, or keep it off until there is a reproable problem, when we can turn it on selectively.

Like this tip? Check out my book, C # 4.0 How-To, where you’ll finds hundreds of great tips like this one.


Check out my latest book, the essential, in-depth guide to performance for all .NET developers:

Writing High-Performance.NET Code, 2nd Edition by Ben Watson. Available for pre-order:

Concurrency, Performance, Arrays and when Dirty Writes are OK

This article will show how to increase the performance of a rather simple algorithm up to 80%, by showing how we can accept a loss in absolutely accuracy, and also taking advantage of how processors work.

Introduction

When we talk about multiple threads using a shared resource, often the first thing we think of is how to synchronize access to that resource so that it is always in a valid, deterministic state. There are, however, many times when the exact opposite approach is desired. Sometimes it’s appropriate to sacrifice accuracy in favor of performance.

To demonstrate the examples in this article, I developed a small test driver that will put our various test classes through their paces on multiple threads and measure a couple of key factors: elapsed time and error rate. To see the code for this driver, download the accompanying sample project.

Histogram

Recently, I needed to implement something that, reduced to essentials, is a histogram. It needed an array of counts and an integer tracking how many samples had been added. Here’s a simplified version of just the histogram functionality:

class Histogram
{
    protected long sampleCount;
    protected ushort[] sampleValueCounts;

    public virtual long SampleCount { get { return sampleCount; } }
    public ushort[] SampleValueCounts { get { return sampleValueCounts; } }

    public Histogram(int range)
    {
        // + 1 to allow 0 - range, inclusive
        this.sampleValueCounts = new ushort[range + 1];
    }

    public virtual void AddSample(int value)
    {
        ++sampleValueCounts[value];
        ++sampleCount;
    }
}

Pretty simple, right?

Now let’s add the requirement that this needs to be access from multiple threads. How is that going to affect the implementation? How do we ensure that sampleCount and the sum of sampleValueCounts[] stay in sync?

The obvious solution is to add a lock in AddSample:

lock(sampleLock)
{
    ++sampleValueCounts[value];
    ++sampleCount;
}
    

Let’s add another requirement: performance. Does the locked version of AddSample perform well enough? Maybe—we should absolutely measure and find out. In my case, I knew some additional details in how the system worked and had past experience to think that I may want to reconsider the lock.

I knew that there would be many thousands of instances of the Histogram and that every second, hundreds to thousands of them would need to be updated. This could be very hot code.

AddSample is a very cheap function—two increments! By adding a lock, even one that most likely runs completely in user mode, I may have significantly increased the time it takes to execute this method. We’ll see an actual measurement below, and it’s not quite that bad in this case, but we can do better.

Lock first to Ensure Correctness

You should always try it first with a lock—make it correct first, then optimize. If your performance is fine with the lock, then you don’t need to go any further—just stop and work on something more important.

Before we add a lock, though, let’s see how the basic histogram performs with no locking and multiple threads:

Type: Histogram

Adding 100,000,000 samples on 32 threads

Elapsed: 00:00:10.0959830

SampleCount: 13,641,046 (Error: -86.359%)

Sum: 99,969,354 (Error: -0.031%)

On my 4 core machine, this took about 10 seconds. The sum of the histogram values was very close to the number of values we tried to add—definitely within our tolerance. Unfortunately, SampleCount is way off.

Intuitively, this makes sense. SampleCount is updated on every single sample, so between all the threads, there is ample opportunity to race and obliterate this value. But the array—not so much. Since I’m testing with a random distribution, there is very low likelihood that there will be a conflict in a particular slot.

Let’s see what happens when we add a lock:

class HistogramLocked : Histogram
{
    private object addLock = new object();

    public HistogramLocked(int range) : base(range) { }

    public override void AddSample(int value)
    {
        lock (addLock)
        {
            ++sampleValueCounts[value];
            ++sampleCount;
        }
    }
}

Type: HistogramLocked

Adding 100,000,000 samples on 32 threads

Elapsed: 00:00:08.0839173

SampleCount: 100,000,000 (Error: 0.000%)

Sum: 100,000,000 (Error: 0.000%)

Woah, our time decreased! Actually, on my home machine it decreased. On my work machine (which has faster and more processors) the time did actually increase by about 10% (proving the point above: you know nothing until you measure).

In most cases, we should just stop here. We’ve ensured a correct system for very little cost. You would need to have a good reason to try to optimize this further.

Since we saw that there weren’t that many conflicts on the array, what if we just protect the sampleCount increment, and do that with an Interlocked.Increment() method?

class HistogramInterlocked : Histogram
{
    public HistogramInterlocked(int range) : base(range) { }

    public override void AddSample(int value)
    {
        ++sampleValueCounts[value];
        Interlocked.Increment(ref this.sampleCount);
    }
}

Type: HistogramInterlocked

Adding 100,000,000 samples on 32 threads

Elapsed: 00:00:10.7659328

SampleCount: 100,000,000 (Error: 0.000%)

Sum: 99,957,294 (Error: -0.043%)

We may as well just use a lock and get 100% accuracy in both counts.

Approximation can be Good Enough

Want to eke out even more performance? To do this without a lock, you need to give up one attribute: correctness. If there are enough samples, then missing a some is fine. You just need to do two things:

  1. Ensure your algorithm can work in the face of slightly incorrect data
  2. Minimize the error as cheaply as possible.

Once you develop an algorithm that approximates a result, you should be able to measure the error rate to validate that the performance gain is worth the loss of accuracy.

Now let’s see if we can get an approximate SampleCount that’s “good enough.”

Instead of having all threads increment a single value, they can all increment their own value. We “bucketize” the sampleCount variable. When we need the real total, we can just add them up, and, in effect, transfer some of the CPU cost to a more rare operation.

class HistogramThreadBuckets : Histogram
{
    private long[] valueBuckets;

    public long[] ValueBuckets { get { return this.valueBuckets; } }

    public override long SampleCount
    {
        get
        {
            long sum = 0;
            for (int i = 0; i < this.valueBuckets.Length; ++i)
            {
                sum += this.valueBuckets[i];
            }
            return sum;
        }
    }

    public HistogramThreadBuckets(int range, int valueBuckets) : base(range) 
    {
        this.valueBuckets = new long[valueBuckets];
    }

    public override void AddSample(int value)
    {
        ++sampleValueCounts[value];

        int bucket = Thread.CurrentThread.ManagedThreadId % this.valueBuckets.Length;
        ++valueBuckets[bucket];            
    }
}

I run this algorithm with multiple bucket counts to see the difference:

Type: HistogramThreadBuckets

Adding 100,000,000 samples on 32 threads

Elapsed: 00:00:09.1901657

ValueCount Buckets: 4

SampleCount: 92,941,626 (Error: -7.058%)

Sum: 99,934,033 (Error: -0.066%)

Type: HistogramThreadBuckets

Adding 100,000,000 samples on 32 threads

Elapsed: 00:00:06.9367826

ValueCount Buckets: 8

SampleCount: 96,263,770 (Error: -3.736%)

Sum: 99,938,926 (Error: -0.061%)

Type: HistogramThreadBuckets

Adding 100,000,000 samples on 32 threads

Elapsed: 00:00:06.6882437

ValueCount Buckets: 16

SampleCount: 98,274,025 (Error: -1.726%)

Sum: 99,954,021 (Error: -0.046%)

Type: HistogramThreadBuckets

Adding 100,000,000 samples on 32 threads

Elapsed: 00:00:04.6969067

ValueCount Buckets: 32

SampleCount: 99,934,543 (Error: -0.065%)

Sum: 99,936,526 (Error: -0.063%)

Cool, we just cut our time in half! Something about this should seem weird, though. How can this be significantly faster than the naïve algorithm when neither of them use locks? There’s no contention anyway!

Well, actually, there is. These buckets likely exist in the various caches for multiple processors, and when you modify one, a certain amount of communication goes on between CPUs to resolve conflicts and invalidate the caches. The more variables there are, the less likely this will happen.

Know Your Cache Line Size

Can we do even better?

If we know that all our CPUs are going to need to coordinate among cache lines, can we ensure we have NO conflicts between our threads? If we know the size of a cache line and absolutely guaranteed that each thread went to a different cache line, then we could take complete advantage of the CPU caches.

To get the size of a cache line, use one of many CPU-information tools available on the Internet. I used one freeware utility called CPU-Z. In my case, the cache line is 64-bytes, so I just need to ensure that the buckets holding the values are at least 64 bytes long. Since a long is 8 bytes, I can just pad out a struct to do this (or just multiply the size of the array and use only every nth entry).

The other thing we need to do is ensure there are no collisions between threads on the buckets. In the previous code, I just hashed the ManagedThreadId into the buckets, but this isn’t reliable since we don’t know the thread ids that we’ll get. The solution is just to send in our own “thread id” that we can reliably map to a unique bucket.

class HistogramThreadBucketsCacheLine : Histogram
{
    public struct ValueBucket
    {
        private long _junk0;
        private long _junk1;
        private long _junk2;
        
        public long value;

        private long _junk4;
        private long _junk5;
        private long _junk6;
        private long _junk7;            
    };

    private ValueBucket[] valueBuckets;

    public ValueBucket[] ValueBuckets { get { return this.valueBuckets; } }

    public override long SampleCount
    {
        get
        {
            long sum = 0;
            for (int i = 0; i < this.valueBuckets.Length; ++i)
            {
                sum += this.valueBuckets[i].value;
            }
            return sum;
        }
    }

    public HistogramThreadBucketsCacheLine(int range, int valueBuckets)
        : base(range) 
    {
        this.valueBuckets = new ValueBucket[valueBuckets];
    }

    public override void AddSample(int value, int threadId)
    {
        ++sampleValueCounts[value];

        ++valueBuckets[threadId].value;
    }
}

And the output is:

Type: HistogramThreadBucketsCacheLine

Adding 100,000,000 samples on 32 threads

Elapsed: 00:00:02.0215371

SampleCount: 100,000,000 (Error: 0.000%)

Sum: 99,761,090 (Error: -0.239%)

We more than halved it again! Not too shabby! Smile

Summary

By being willing to accept some loss of accuracy, and taking advantage of how processors work, we were able to reduce the running time of a fairly simple and superficially efficient algorithm by 80%. As with all performance investigations, your mileage may vary, and lots depends on the data your manipulating and the hardware it runs on. Optimizations like these should be quite rare, and only in places you absolutely need them.

Download the sample code project.

Like this tip? Check out my book, C # 4.0 How-To, where you’ll finds hundreds of great tips like this one.


Check out my latest book, the essential, in-depth guide to performance for all .NET developers:

Writing High-Performance.NET Code, 2nd Edition by Ben Watson. Available for pre-order:

Keep API Usage Simple

One lesson that I’m appreciating more every week is that old acronym, K.I.S.S. – Keep It Simple, Stupid. Simple code is best. The highest cost of most software is maintenance—and you don’t want maintenance to include a lot of “how the heck does this work?”

This simplicity does not apply to just your own code. Most API frameworks provide multiple ways of doing things, but if you don’t need it, don’t use it.

For example, I’ve been working a lot with the Task Parallel Library, and it’s great – it really is an awesome way of doing asynchronous programming. However, when you get to continuations, there are so many options, it can quickly make your code a bewildering mix of usage patterns, if you’re not careful.

You can have continuations called only when the task fails, or is canceled, or only when it succeeds, or only when it does not succeed. You can chain continuations, cancel them, and there are all sorts of scheduling options, and much more.

This API is powerful, and I’m grateful it’s all there, but when you need to have a large team work on a single code base, it’s helpful necessary to enforce some simplifying constraints. One thing we’ve done, specifically with the Task Parallel Library, is to require everyone to use just one of the many possible patterns. This way, no matter what part of the code we’re looking at, we can understand exactly how Tasks work. It takes the guesswork out, and reduces maintenance costs. This kind of thing is especially critical for complex areas of the code – i.e., asynchronous programming.

Takeaway: you don’t have to use every possible API feature or pattern—just pick one and enforce consistency and simplicity.


Check out my latest book, the essential, in-depth guide to performance for all .NET developers:

Writing High-Performance.NET Code, 2nd Edition by Ben Watson. Available for pre-order:

Activator.CreateInstance: Slow vs. Less-Slow

In the system I’m working on, there is a lot of runtime type resolution, e.g., lines like this:

var obj = Activator.CreateInstance(type, param1, param2, param3)

The params are arguments to the constructor of the type. The type itself is ultimately given through some configuration or otherwise-dynamic means.

Since we do a lot of this (many times per second), we’d like to ensure that instance creation is as fast as it can be. The method given above is not fast.

When this overload of CreateInstance is called, .Net has to do a lot of work to make sure it works: find the right constructor, verify that all the argument types match up, etc. This can be painfully slow, especially when, in a closed system, you can do a lot of offline validation to ensure that types are correctly specified.

Fortunately, Activator has another overload that is quite a bit faster, if you can use it.

Activator.CreateInstance(type)

This will call the default constructor of the type. However, we still have the problem of passing in those arguments. There are a few ways we could do this, but one of the simplest is to ensure that all the types you’re doing this for implement a common initialization interface, as in this sample program:

interface IPerson
{
    void Initialize(string name, DateTime dob, int weight);
}

class Employee : IPerson
{
    public Employee()
    {
    }

    public Employee(string name, DateTime dob, int weight)
    {
        Initialize(name, dob, weight);
    }

    public Employee(string name, DateTime dob)
        : this(name, dob, -1)
    {
    }

    public void Initialize(string name, DateTime dob, int weight)
    {
        this.name = name;
        this.dob = dob;
        this.weight = weight;
    }

    private string name;
    private DateTime dob;
    private int weight;
}

class Program
{
    static void Main(string[] args)
    {
        const int iterations = 1000000;

        Console.WriteLine("Timing Activator.CreateInstance(type, params)...");
        var employees = new IPerson[iterations];

        var stopwatch = Stopwatch.StartNew();

        for (int i = 0; i < iterations; ++i)
        {
            employees[i] = Activator.CreateInstance(typeof(Employee), 
                "Bob", DateTime.Now, 220) as IPerson;
        }

        stopwatch.Stop();

        Console.WriteLine("Total time: {0} for {1:N0} employees", 
            stopwatch.Elapsed.ToString(), iterations);
        Console.WriteLine();

        Console.WriteLine("Timing Activator.CreateInstance(type) + Initialization...");
        
        var employees2 = new IPerson[iterations];

        var stopwatch2 = Stopwatch.StartNew();            

        for (int i = 0; i < iterations; ++i)
        {
            employees2[i] = Activator.CreateInstance(typeof(Employee)) as IPerson;
            employees2[i].Initialize("Bob", DateTime.Now, 220);
        }

        stopwatch2.Stop();

        Console.WriteLine("Total time: {0} for {1:N0} employees", 
            stopwatch2.Elapsed.ToString(), iterations);
    }
}

What do you think the time difference in the two approaches is?

Timing Activator.CreateInstance(type, params)…

Total time: 00:00:05.4765664 for 1,000,000 employees

Timing Activator.CreateInstance(type) + Initialization…

Total time: 00:00:01.6007687 for 1,000,000 employees

About 3.5x faster. Pretty good. In practice, the improvement will vary. In some of our own timing experiments, we actually saw a much better speedup.

Like this tip? Check out my book, C # 4.0 How-To, where you’ll finds hundreds of great tips like this one.


Check out my latest book, the essential, in-depth guide to performance for all .NET developers:

Writing High-Performance.NET Code, 2nd Edition by Ben Watson. Available for pre-order:

Performance and Other Issues with System.Enum

I’ve been doing a lot of very intense .Net coding at work for the last few months and it’s very gratifying to see that .Net can handle some pretty serious high-load scalable server work. We are doing some pretty amazing things. However, there are all sorts of gotchas—you do have to learn how to do it correctly (but that’s true of any technology).

One of the things we’re most concerned about right now is performance, and where performance is concerned, one of the big gotchas is the .Net Framework Class Library. Don’t get me wrong, for 99.99% of all .Net projects, the performance is perfectly adequate and you don’t have to care (much). On the other hand, if you’re dealing with highly-scalable systems, you should definitely validate the performance of any general-purpose library you use.

As with all performance question, the only 100% solid advice in all situations is: measure, measure, measure.

General Purpose Methods May Not Be Fast

I did a profiler run on one of our components the other day and a few methods showed up that I would never expect to see in a profiler trace:

We were calling these methods a lot. In my mind, they both basically boiled down to logical AND (&) statements. Unfortunately that’s not the case.

If you use an IL decompiler like ILSpy to examine the code of these methods, you’ll see they do quite a bit more. For example, HasFlag also checks whether the types are equal—useful, but that’s a lot more expensive than a simple & check.

IsDefined is even worse. There are half a dozen checks for specific types, followed by an allocation of an array containing all the enum values, and finally a binary search. If your enums are string types, then it’s just a linear search with string comparisons.

It’s easy to understand why these methods are so heavy—they’re being extra cautious for correctness-sake. That’s probably what you want in a general-purpose framework.

However, if your goal is performance and you have a closed system, complete control of your code, and adequate tests, then you can make better decisions.

Rather than do this:

if (bookFlags.HasFlag(BookTypes.Fiction))

Do this instead:

if ((bookFlags & BookTypes.Fiction) != 0)


As for IsDefined, just don’t use it. Or use it in debug-only assertions to validate functionality.

Another Enum method to avoid if you can is ToString(), especially on enumerations that have [Flags].

HasFlag Gotcha

Suppose you have this code:

[Flags]
enum NodeFlags
{
    Exception = 1,
    Failure = 2,
    Canceled = 4,
    TimedOut = 8,
 
    AnyFailure = Exception | Canceled | TimedOut
}
 
if (node.Flags.HasFlag(NodeFlags.Failure)
    || node.Flags.HasFlag(NodeFlags.TimedOut)
    || node.Flags.HasFlag(NodeFlags.Exception))

You may be tempted to do this:

if (node.Flags.HasFlag(NodeFlags.AnyFailure))

This will not work. It will check that ALL of the bits are set, not just one of them.

You will need to do this:

if ((node.Flags & NodeFlags.AnyFailure) != 0)

We saw that around 5% of our CPU time was being spent just in Enum.IsDefined and Enum.HasFlag. With these changes, we reduce that to approximately 0.

If you find tips like these helpful, you’ll love my book, C# 4.0 How-To.


Check out my latest book, the essential, in-depth guide to performance for all .NET developers:

Writing High-Performance.NET Code, 2nd Edition by Ben Watson. Available for pre-order:

A WPF Numeric Entry Control with Pop-up Calculator

Part 1 – WPF Numeric Entry Control

Part 2 – This article

Download Source Code

When WPF first shipped, there was a noticeable lack of certain controls we’ve become used to in Win32 and WinForms: Calendar, DateTimePicker, and NumericUpDown. WPF 4 adds Calendar and DatePicker, but not anything for numeric entry.

I described how to create a numeric entry control in a previous article. In this article, I will follow that up by adding a popup calculator to allow you to quickly manipulate the number.

If you find this article useful, please consider buying my best-selling book, Writing High-Performance .NET Code.

Adding a Popup Calculator

Now that we have a basic numeric entry control, let’s extend it by adding the power of a keyboard-driven calculator popup window.

If you’ve used Quicken or the now-sadly-defunct Microsoft Money, you’ve seen a feature that pops up a calculator window whenever you hit +, –, *, or / in a number field.

Here are some further requirements for such a control:

  • It should be activated when the user types +, –, *, or /
  • It should be dismissed if the user hits Escape, Enter, or clicks anywhere outside the calculator (which is considered equivalent to Enter, not escape)
  • Both mouse and keyboard input should be handled
  • This version only handles integers
  • It should handle Backspace key to erase previously-input character
  • It should be visually compact
  • It should allow the user to string computations together. A + B – C / D * E

Extend the Numeric Entry Control

We first need to come up with a way to trigger the calculator in our numeric entry control. This is going to simply be if the user hits any math-operation character, such as +, –, *, or /.

First, we’ll need to define the allowed operations and a way to associate keyboard keys with math operations:

public enum MathOperation
{
    None = 0,
    Add,
    Subtract,
    Multiply,
    Divide
};

Now, let’s subclass NumericEntryControl with a new class that adds some additional keyboard handling.

class NumericEntryWithCalcControl : NumericEntryControl
{
    static Dictionary<Key, MathOperation> _keyToOp =
        new Dictionary<Key, MathOperation>();

    static NumericEntryWithCalcControl()
    {
        //associate keyboard keys with a math operation
        _keyToOp[Key.Add] = MathOperation.Add;
        _keyToOp[Key.Subtract] = MathOperation.Subtract;
        _keyToOp[Key.Multiply] = MathOperation.Multiply;
        _keyToOp[Key.Divide] = MathOperation.Divide;

#if DEBUG
        //easier keys on a laptop
        _keyToOp[Key.A] = MathOperation.Add;
        _keyToOp[Key.S] = MathOperation.Subtract;
        _keyToOp[Key.M] = MathOperation.Multiply;
        _keyToOp[Key.D] = MathOperation.Divide;
#endif
    }
}

With this bookkeeping down, we can intercept the keystrokes and show our calculator window (which we’ll define later) in the right spot. We also should handle when the window closes.

private CalcWindow _calc = null;

protected override void OnKeyDown(KeyEventArgs e)
{
    MathOperation op = MathOperation.None;
    if (_keyToOp.TryGetValue(e.Key, out op))
    {
        e.Handled = true;
        HandleOperation(op);
    }
    else
    {
        e.Handled = false;
        base.OnKeyDown(e);
    }
}

private void HandleOperation(MathOperation mathOperation)
{
    //show the calc dialog and initialize with Value and Op
    if (mathOperation != MathOperation.None)
    {
        _calc = new CalcWindow(Value, mathOperation);
        _calc.Closed += new EventHandler(calc_Closed);
        Point point = this.PointToScreen(new Point(0, 0));

        //adjust location to correct for DPI settings
        PresentationSource source = PresentationSource.FromVisual(this);

        double dpiX = 96.0 * source.CompositionTarget.TransformToDevice.M11;
        double dpiY = 96.0 * source.CompositionTarget.TransformToDevice.M22;

        _calc.Left = point.X * 96.0 / dpiX;
        _calc.Top = point.Y * 96.0 / dpiY;

        _calc.Show();
    }
}

private void calc_Closed(object sender, EventArgs e)
{
    if (_calc != null)
    {
        this.Value = _calc.CurrentValue;
        _calc.Closed -= new EventHandler(calc_Closed);
        _calc = null;
    }
}

Notice in ProcessOperation that the location of the calculator window is set to the upper left corner of the NumericEntryControl and it takes into account the current DPI. This is important if you’re using anything other than the standard 96 DPI.

Create the Calculator

calc_demo2

The actual calculator is a WPF window with no border (or a thin one), a textbox, and buttons representing a standard calculator layout.

The screenshot to the right shows the design layout of this window. The C button clears the input and sets the current value to 0. The left arrow erases the last character you input.

Since this window is designed to popup over other controls, I wanted to keep it as compact as possible.

The XAML code looks like this:

<Window x:Class="NumericEntryDemo.CalcWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:my="clr-namespace:NumericEntryDemo"
        Title="CalcWindow" WindowStyle="None"
        SizeToContent="WidthAndHeight"
        WindowStartupLocation="Manual"
        ResizeMode="NoResize"
        BorderThickness="1"
        >
    <DockPanel>
        <TextBox Name="_textbox"
                 DockPanel.Dock="Top"
                 Margin="2"
                 IsReadOnly="True"
                 Text="{Binding RelativeSource={RelativeSource FindAncestor,
                    AncestorType=my:CalcWindow, AncestorLevel=1}, Path=CurrentValue}"
                 TextAlignment="Right" />
        <UniformGrid Columns="4" Rows="5" Width="100" Height="100" Margin="2">
            <Button Name="_button7" Content="7" Click="digitButton_Click"/>
            <Button Name="_button8" Content="8" Click="digitButton_Click"/>
            <Button Name="_button9" Content="9" Click="digitButton_Click"/>
            <Button Name="_buttonDivide" Content="÷"  Click="opButton_Click"/>
            <Button Name="_button4" Content="4" Click="digitButton_Click"/>
            <Button Name="_button5" Content="5" Click="digitButton_Click"/>
            <Button Name="_button6" Content="6" Click="digitButton_Click"/>
            <Button Name="_buttonMultiply" Content="×"  Click="opButton_Click"/>
            <Button Name="_button1" Content="1" Click="digitButton_Click"/>
            <Button Name="_button2" Content="2" Click="digitButton_Click"/>
            <Button Name="_button3" Content="3" Click="digitButton_Click"/>
            <Button Name="_buttonSubtract" Content="-" Click="opButton_Click"/>
            <Button Name="_button0" Content="0" Click="digitButton_Click"/>
            <!-- empty space -->
            <Rectangle/>
            <Rectangle/>
            <Button Name="_buttonAdd" Content="+" Click="opButton_Click"/>
            <Button Name="_buttonClear" Content="C" Click="clearButton_click"/>
            <Button Name="_buttonErase" Content="?" Click="backButton_Click"/>
            <Button Name="_buttonEquals" Content="=" Click="equalsButton_Click"/>
        </UniformGrid>
    </DockPanel>
    <Window.Background>
        <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
            <GradientStop Color="White" Offset="0" />
            <GradientStop Color="#FFDBDBDB" Offset="1" />
        </LinearGradientBrush>
    </Window.Background>
</Window>

All of the click handlers and binding targets will be filled out in the code-behind.

To start with, we need a few housekeeping variables:

  • The original value upon starting the calculator, just in case after all the calculations the user just hits Escape
  • A way to track whether we’ve canceled the whole thing
  • The current operation
  • The current input, in both string and number form
  • The previously calculated value, allowing you to string together calculations like “123 + 456 / 2 * 29”
  • Map buttons and keystrokes to numbers, math operations, and the other commands.

With that, we can see the beginning of our class:

public partial class CalcWindow : Window
{
    private int _initialValue = 0;
    private bool _canceled = false;
    private MathOperation _currentOp = MathOperation.None;

    //value of current input
    public static readonly DependencyProperty CurrentValueProperty =
        DependencyProperty.Register("CurrentValue", typeof(int),
        typeof(CalcWindow), new PropertyMetadata(0));

    //current input in string form
    public static readonly DependencyProperty CurrentInputProperty =
        DependencyProperty.Register("CurrentInput", typeof(string),
        typeof(CalcWindow), new PropertyMetadata(""));

    //previously calculated value
    public static readonly DependencyProperty PreviousValueProperty =
        DependencyProperty.Register("PreviousValue", typeof(int),
        typeof(CalcWindow), new PropertyMetadata(0));

    private static readonly Dictionary<Key, int> _keyDigits =
        new Dictionary<Key, int>();
    private static readonly Dictionary<Key, MathOperation> _keyOps =
        new Dictionary<Key, MathOperation>();

    private readonly Dictionary<Button, int> _buttonDigits =
        new Dictionary<Button, int>();
    private readonly Dictionary<Button, MathOperation> _buttonOps =
        new Dictionary<Button, MathOperation>();

    static CalcWindow()
    {
        _keyDigits[Key.D0] = 0;
        _keyDigits[Key.D1] = 1;
        _keyDigits[Key.D2] = 2;
        _keyDigits[Key.D3] = 3;
        _keyDigits[Key.D4] = 4;
        _keyDigits[Key.D5] = 5;
        _keyDigits[Key.D6] = 6;
        _keyDigits[Key.D7] = 7;
        _keyDigits[Key.D8] = 8;
        _keyDigits[Key.D9] = 9;

        _keyDigits[Key.NumPad0] = 0;
        _keyDigits[Key.NumPad1] = 1;
        _keyDigits[Key.NumPad2] = 2;
        _keyDigits[Key.NumPad3] = 3;
        _keyDigits[Key.NumPad4] = 4;
        _keyDigits[Key.NumPad5] = 5;
        _keyDigits[Key.NumPad6] = 6;
        _keyDigits[Key.NumPad7] = 7;
        _keyDigits[Key.NumPad8] = 8;
        _keyDigits[Key.NumPad9] = 9;

        _keyOps[Key.Add] = MathOperation.Add;
        _keyOps[Key.Subtract] = MathOperation.Subtract;
        _keyOps[Key.Multiply] = MathOperation.Multiply;
        _keyOps[Key.Divide] = MathOperation.Divide;

#if DEBUG
        _keyOps[Key.A] = MathOperation.Add;
        _keyOps[Key.S] = MathOperation.Subtract;
        _keyOps[Key.M] = MathOperation.Multiply;
        _keyOps[Key.D] = MathOperation.Divide;
#endif

    }

    public int CurrentValue
    {
        get
        {
            return (Int32)GetValue(CurrentValueProperty);
        }
        set
        {
            SetValue(CurrentValueProperty, value);
        }
    }

    public string CurrentInput
    {
        get
        {
            return GetValue(CurrentInputProperty) as string;
        }
        set
        {
            SetValue(CurrentInputProperty, value);
        }
    }

    public int PreviousValue
    {
        get
        {
            return (Int32)GetValue(PreviousValueProperty);
        }
        set
        {
            SetValue(PreviousValueProperty, value);
        }
    }

    public CalcWindow(int initialValue, MathOperation operation)
    {
        _initialValue = initialValue;
        _currentOp = operation;

        CurrentValue = _initialValue;
        PreviousValue = CurrentValue;

        InitializeComponent();

        InitializeButtons();
    }

    private void InitializeButtons()
    {
        _buttonDigits[_button0] = 0;
        _buttonDigits[_button1] = 1;
        _buttonDigits[_button2] = 2;
        _buttonDigits[_button3] = 3;
        _buttonDigits[_button4] = 4;
        _buttonDigits[_button5] = 5;
        _buttonDigits[_button6] = 6;
        _buttonDigits[_button7] = 7;
        _buttonDigits[_button8] = 8;
        _buttonDigits[_button9] = 9;

        _buttonOps[_buttonAdd] = MathOperation.Add;
        _buttonOps[_buttonSubtract] = MathOperation.Subtract;
        _buttonOps[_buttonMultiply] = MathOperation.Multiply;
        _buttonOps[_buttonDivide] = MathOperation.Divide;
    }
}

All that’s left is to the actual work of handling input. Since input can be from both keyboard and button clicks, let’s first define methods to handle the general operations, and we can hook up the input later.

Generic Input Handling

First, we’ll look at the generic input handlers. These are called by the mouse and keyboard handlers and they return true so they can notify the caller of whether they actually handled the operation.

The “C” button on the calculator will not only clear the current input, but set the current value to 0 (I’m not going to bother implementing a “CE” button that clears just the current input, but it would be easy to add).

private bool HandleClear()
{
   CurrentInput = "";
   CurrentValue = 0;

   return true;
}

When the user hits escape, you want to close the window, after setting the value back to the initial one.

private bool HandleEscape()
{
    _canceled = true;
    CurrentValue = _initialValue;

    Close();

    return true;
}

We need the _canceled flag because, as we’ll see below, when the window is deactivated, under normal circumstances we want to complete the current operation, but in the canceled case we want to do nothing.

When a user hits Enter or presses the Equals button, the current operation should be completed and the window closed. In this control, since we also want the current operation to be completed when the window is deactivated, hitting Equals will just cause the window to close and we’ll handle the calculation in the deactivation code.

private bool HandleEquals()
{
    //The final operation will be 
    //handled when the window closes
    Close();
    return true;
}

This calculator provides a back button to erase the previously-entered digit. If the input becomes empty, then the current value is set to 0.

private bool HandleBack()
{
    if (!string.IsNullOrEmpty(CurrentInput))
    {
        CurrentInput = CurrentInput.Substring(0, CurrentInput.Length - 1);
        //this is guaranteed to succeed because we validate when we add digits
        if (!string.IsNullOrEmpty(CurrentInput))
        {
            CurrentValue = Int32.Parse(CurrentInput);
        }
        else
        {
            CurrentValue = 0;
        }
    }
    return true;
}

When accepting new input, our button and keyboard handlers will ensure that the user can only enter digits, but we also need to make sure we handle integer overflow. An easy way to do this is to treat the new digit as a character and append it to the current input and then reparse it.

private bool HandleDigit(int digit)
{
    string newInput = CurrentInput + digit.ToString();
    int temp = 0;
    //make sure the full input is a number
    if (Int32.TryParse(newInput, out temp))
    {
        CurrentInput = newInput;
        CurrentValue = temp;
        return true;
    }
    return false;
}

Finally, when the user selects an operation we need to do one of two things. If there is no current input, then we can just change the current operation to the new one. This lets you change your mind, say if you hit ‘+’, but really wanted ‘-‘.

On the other hand, if the user has already entered a number, then you know you’re finishing up the current expression and the user wants to calculate the results and start a new expression. As an example,  consider the expression A + B. A is the initial value of the NumericEntryControl, the + is what triggered the calculator to show up, and B is the number the user entered after the calculator was visible. When the next operation is input, A + B should be resolved, placed into A, the current operation set, and the user can now enter the next B, and so on.

private bool HandleOperation(MathOperation op)
{
    if (CurrentInput.Length > 0)
    {
        ProcessCurrentOperation();
    }
    _currentOp = op;
    return true;
}

With that, we’ve seen all of the generic input handling. Now let’s move on to the actual math.

Doing the Math

The ProcessCurrentOperation method is the heart of this control as it updates all the values according to the user’s input. Here too we need to consider what happens if the user’s calculations cause an integer overflow. To detect this we need to use a combination of the checked keyword and some exception handling. To simplify things, if this happens, the whole calculation is canceled and the window closed. We also handle divide by zero errors by just setting the new value to 0.

(The checked keyword tells .NET to issue exceptions when integer math overflows. The default behavior depends on compilation and environment settings, but the unchecked behavior is usually what happens).

private void ProcessCurrentOperation()
{
    if (string.IsNullOrEmpty(CurrentInput))
    {
        return;
    }

    int newValue = 0;
    checked
    {
        try
        {
            switch (_currentOp)
            {
                case MathOperation.Add:
                    newValue = PreviousValue + CurrentValue;
                    break;
                case MathOperation.Subtract:
                    newValue = PreviousValue - CurrentValue;
                    break;
                case MathOperation.Multiply:
                    newValue = PreviousValue * CurrentValue;
                    break;
                case MathOperation.Divide:
                    if (CurrentValue != 0)
                    {
                        newValue = PreviousValue / CurrentValue;
                    }
                    else
                    {
                        newValue = CurrentValue;
                    }
                    break;
                default:
                    Debug.Assert(false, "Invalid operation. Should never happen!");
                    break;
            }

            CurrentInput = "";
            CurrentValue = newValue;
            PreviousValue = newValue;
        }
        catch (OverflowException)
        {
            //will cause the window to close, so we better cancel everything first
            _canceled = true;
            CurrentValue = _initialValue;

            MessageBox.Show("The result overflowed, calculation canceled.");
        }
    }
}

Deactivation

As we said before, deaction should cause the current operation to complete, unless the user has canceled.

protected override void OnDeactivated(EventArgs e)
{
    if (!_canceled)
    {
        ProcessCurrentOperation();
        if (IsVisible)
        {
            //window is still visible if we've 
            //clicked away from the window
            //before finishing calculation
            Close();
        }
    }
    base.OnDeactivated(e);
}

The only thing that remains is hooking up mouse and keyboard input to our existing methods.

Mouse Handling

These are already referenced in the XAML, and all they do is forward to the  generic handlers.

void opButton_Click(object sender, RoutedEventArgs e)
{
    MathOperation op = _buttonOps[sender as Button];
    e.Handled = HandleOperation(op);
}

void digitButton_Click(object sender, RoutedEventArgs e)
{
    int digit = _buttonDigits[sender as Button];
    e.Handled = HandleDigit(digit);
}

private void clearButton_click(object sender, RoutedEventArgs e)
{
    e.Handled = HandleClear();
}

private void backButton_Click(object sender, RoutedEventArgs e)
{
    e.Handled = HandleBack();
}

private void equalsButton_Click(object sender, RoutedEventArgs e)
{
    e.Handled = HandleEquals();
}

Keyboard Handling

To handle the keyboard, we need to preempt the normal message flow by looking at the preview messages (which flow from the top of the UI hierarchy down, rather than the normal messages which bubble from the bottom to the top). If we don’t do this, then when we hit keys like Enter, they go to the button with the current focus, when instead we want it to always cause the Equals functionality.

protected override void OnPreviewKeyDown(KeyEventArgs e)
{
    /*take over all keyboard input
     * this is important because if a button has focus 
     * and we hit enter then the button will be clicked
     * */

    int digit = 0;
    MathOperation op = MathOperation.None;
    if (_keyDigits.TryGetValue(e.Key, out digit))
    {
        e.Handled = HandleDigit(digit);
    }
    else if (_keyOps.TryGetValue(e.Key, out op))
    {
        e.Handled = HandleOperation(op);
    }
    else
    {
        switch (e.Key)
        {
            case Key.Enter:
                e.Handled = HandleEquals();
                break;
            case Key.Escape:
                e.Handled = HandleEscape();
                break;
            case Key.Back:
                e.Handled = HandleBack();
                break;
            case Key.C:
                e.Handled = HandleClear();
                break;
            default:
                e.Handled = false;
                break;
        }
    }
    base.OnPreviewKeyDown(e);
}

There you have it, a working pop-up calculator, usable from any other control you can subclass. As is often the case, there are a lot more features you could add to this basic implementation:calc_demo3

  • Undo
  • Floating-point support
  • Button highlights with corresponding key presses
  • More advanced display, showing current operator, previous values, etc.
  • More robust handling of overflow

Download Source Code

If you find this article useful, you will love my book, C# 4.0 How-To, which is filled with tips such as this.


Check out my latest book, the essential, in-depth guide to performance for all .NET developers:

Writing High-Performance.NET Code, 2nd Edition by Ben Watson. Available for pre-order:

Another C# 4.0 How-To Book Give-away

In celebration of the beginning of the school year here in the USA, I’m going to give away a few more copies of my book C# 4.0 How-To .

If you’ve ever wanted a step-by-step guide with practicable code examples for hundreds of tasks in C#, .Net, and Windows, then this is the book for you. So far, I’m very pleased with the reviews its gotten (if you already have the book and haven’t left a review, why not? Smile)

Just leave a comment on this post, and I’ll choose two people at random. You must be in the US or Canada.

Also, for twitter users, if you retweet a link to this post using the hashtag #cs4howto, I’ll include you in the drawing as well.

The more comments and #cs4howto re-tweets there are, the more books I’ll give away!


Check out my latest book, the essential, in-depth guide to performance for all .NET developers:

Writing High-Performance.NET Code, 2nd Edition by Ben Watson. Available for pre-order:

Measure Amount of Data to Serialize with a Null Stream

If you’ve got to serialize some data, especially in a binary format, it’s common to output the length of the data. This is useful for versioning, random access, knowing when you’re done reading the records, among other reasons.

Therefore, you need to know the size of the data you’re going to serialize. There are a few ways to do this:

  1. Measure the position you’re at, write the data, measure the new position, subtract, and that’s your length.
  2. If you want to write the length first (which is usually better), you can write a dummy value, such as 0, then writing the data, then backing up in the stream, and writing the real value.
  3. If you can’t back up the stream (very possible in some situations, or undesirable in others), you can measure the amount of data before you write. However, now you have to maintain that code in addition to the actual serialization.
  4. My solution presented here, avoids having to maintain separate code by writing the data to a null stream which does not write any data, but keeps track of how much data was “written.”
class NullStream : System.IO.Stream
{
    public override bool CanRead { get { return false; } }
 
    public override bool CanSeek { get { return false; } }
 
    public override bool CanWrite {get { return true; } }
 
    public override void Flush() { /*do nothing*/ }
 
    public override long Length { get { return Position; } }
 
    private long _position = 0;
    public override long Position 
    { 
        get 
        {
            return _position;
        }
        set
        {
            _position = value;
        }
    }
 
    public override int Read(byte[] buffer, int offset, int count)
    {
        throw new InvalidOperationException();
    }
 
    public override void Write(byte[] buffer, int offset, int count)
    {
        Position += count;
    }
 
    public override long Seek(long offset, System.IO.SeekOrigin origin)
    {
        throw new InvalidOperationException();
    }
 
    public override void SetLength(long value)
    {
        throw new InvalidOperationException();
    }
}

You can use it like this:

long GetDataSize()
{
    using (NullStream stream = new NullStream())
    {
        if (SaveData(stream))
        {
            return stream.Position;
        }
    }
    return 0;
}

There is a downside to something like this: you’re still essentially doing a lot of the work of serialization. Sure, you’re not writing out the bytes anywhere, but if, say, you need to encode a string as bytes before writing to the stream, that’s still going to happen.

Still, this technique made sense in my case, maybe it will work for you.


Check out my latest book, the essential, in-depth guide to performance for all .NET developers:

Writing High-Performance.NET Code, 2nd Edition by Ben Watson. Available for pre-order:

C# 4.0 How-To Available Now!

Well, it’s finally out! Amazon no longer lists the book as available for pre-sale, and it should be shipping to purchasers today or tomorrow. If you’re a B&N shopper, you can also order it there, or grab it in stores within a few days.

From the product description:

Real Solutions for C# 4.0 Programmers

Need fast, robust, efficient code solutions for Microsoft C# 4.0? This book delivers exactly what you’re looking for. You’ll find more than 200 solutions, best-practice techniques, and tested code samples for everything from classes to exceptions, networking to XML, LINQ to Silverlight. Completely up-to-date, this book fully reflects major language enhancements introduced with the new C# 4.0 and .NET 4.0. When time is of the essence, turn here first: Get answers you can trust and code you can use, right now!

Beginning with the language essentials and moving on to solving common problems using the .NET Framework, C# 4.0 How-To addresses a wide range of general programming problems and algorithms. Along the way is clear, concise coverage of a broad spectrum of C# techniques that will help developers of all levels become more proficient with C# and the most popular .NET tools.

Fast, Reliable, and Easy to Use!

  • Write more elegant, efficient, and reusable code
  • Take advantage of real-world tips and best-practices advice
  • Create more effective classes, interfaces, and types
  • Master powerful data handling techniques using collections, serialization, databases, and XML
  • Implement more effective user interfaces with both WPF and WinForms
  • Construct Web-based and media-rich applications with ASP.NET and Silverlight
  • Make the most of delegates, events, and anonymous methods
  • Leverage advanced C# features ranging from reflection to asynchronous programming
  • Harness the power of regular expressions
  • Interact effectively with Windows and underlying hardware
  • Master the best reusable patterns for designing complex programs

I’ll be doing a book giveaway at some point as well, once I get my own shipment. Stay tuned!

Get it from Amazon

Get it from Barnes and Noble


Check out my latest book, the essential, in-depth guide to performance for all .NET developers:

Writing High-Performance.NET Code, 2nd Edition by Ben Watson. Available for pre-order: