Using Lists and Stacks in .NET

If the core software you write consists mostly of lines of business apps, then I'm sure like me, quite a lot of you do. But, did you ever stop to thoroughly explore some of the more esoteric types that are available in the .NET collections namespace?

It might surprise some that, as well as the more commonly known dictionary and array types, .NET has quite a few classes designed for implementing things like FIFO/LIFO Queues, linked lists, and many other structures that you might never have even realised.

Interesting, but if I've Gotten This Far Without Needing Them...

Many will proclaim that if they've gotten this far in their career without knowing about the existence of these extra types, why suddenly start using them?

Like many tools in the developers' toolbox, it's not about suddenly starting to use them, but more a realisation that you now have an extra tool, and you never know when it's going to come in handy. This is exactly what happened to me, and why it prompted me to write this post about the hidden gems available.

On a recent project, I had to research a different way of managing a collection of data in an application I was maintaining. This data, due to its structure, warranted a slight deviation from the norm. As a result, I ended up uncovering some of the collection types I describe below.

Bit Array

The Bit Array class is, in the true sense of the word, just like a normal Array. Under the hood, however, it harbours some very clever tricks.

The idea behind the Bit Array is to store a collection of ones and zeros, represented in individual units as Boolean true/false values. Behind the scenes, however, everything is packed down into bytes/ints as far as possible. This means you can—at least in theory—pack 32 bits of information into the same space that a one-element integer array would occupy.

Bit Arrays can be constructed from byte arrays; so, for example, if you did the following:

You would end up with a Bit Array containing 16 Boolean elements all set to true.

The actual bit pattern set is derived from the bit pattern produced. If you were to turn the individual values into their binar, representations. This is useful for things like compression systems, or taking parallel data and streaming it serially, perhaps down a serial cable, or in a serial network simulation.

You also can take two Bit Arrays and perform useful operations on them, such as 'AND', 'OR', and 'XOR'. This will allow you to perform bit-level operations without having to resort to individual bit twiddling.

Queue

Queues are used to create FIFO (first in first out) structures. This kind of structure is very useful for sequentially processing a set of messages or commands. For example, if you had an internal message bus in your application, you could use the queue to receive the messages coming in from the bus, and make them ready for a processor to use them.

Unlike a normal list, you don't reference items in the queue directly by an index. You add items to the queue by using the following statements:

This will add the three messages such that the last one added will be the last one out.

You get the value at the head by using the reverse of the 'Enqueue' method 'Dequeue', as follows:

string msg1 = myQueue.Dequeue();

you can use the 'Peek' method to check if there is anything present without removing it, and like all the classes in the namespace, the queue presents an IEnumerable iteration interface so you can do things such as 'for each' over the collection.

Stack

Stacks are the opposite of a queue and are used to construct a LIFO (last in first out) structure. The easiest way to picture this is to imagine a stack of plates.

As you put one plate on top of another, the stack grows higher. When you need a plate, you take one from the top of the stack. The last plate added to the stack was the next one out. Stacks are often used for temporary lists of things like parameters while a calculation is performed on them. In fact, some mathematical operations performed using methods, such as reverse polish notation, are inherently based around the concept of a stack.

To add items to a stack, use the 'Push' method. To get the value at the top of the stack, use 'Pop' (to pop off the top value) as follows:

There are others too, such as an ArrayList, SortedList, and a ReadOnlyCollection. However, the one big thing that many may not realise has been added to the collection's name space are the parallel tasking extensions. Along with the addition of the collections in the PLinq (Parallel Linq) namespaces, most of the structures in the standard system.collections namespace have now been extended to include operations such as 'AsParallel'.

What this means is that, when performing Linq queries using these collections, you can apply AsParallel to allow the query to do multiple operations on multiple threads making best use of multi core machines. As well as these extensions, there are a number of interface types, allowing you to build custom data types easily, while using the underlying existing structures to avoid having to re-invent the wheel.

If there's anything you'd like to see covered in this column, please feel free to hunt me down on Twitter where I can be found as @shawty_ds. I also help run a small .NET users group on the Linked-in network, called Lidnug. Please feel free to swing by and say hello, and I'll see what I can do to get your topic included in this column.

MD

Posted by Jim Reid
on 09/01/2014 03:39am

In the Bit Array example:
byte[] myBytes = new byte[5] { 255, 255 };
BitArray myBA3 = new BitArray( myBytes );
(1): Shouldn't the first line read:
byte[] myBytes = new byte[2] { 255, 255 };
The remaining 3 Bytes seem to be redundant.
(2): I not sure why the variable name myBA3 has been so chosen.
Did you mean myBA2 ?
Sorry if I have misunderstood the example, but, if so, I would still be grateful for an explanation.
Many thanks
Jim Reid

RE: MD

Posted by Peter Shaw
on 09/26/2014 07:49am

Hi Jim,
Well spotted, yes that should indeed be only 2 bytes. I think maybe my caffeine level may have been a little low when I typed that. :-)
As for BA3, well not quite sure why 'BA3' but the BA was supposed to be short form of 'BitArray' there's a good chance that was a caffine affected type too.
Come find me on twitter - @shawty_ds I'll see if I can rustle you up a freebie for something dev related for spotting that one :-)
Shawty

Top White Papers and Webcasts

U.S. companies are desperately trying to recruit and hire skilled software engineers and developers, but there is simply not enough quality talent to go around. Tiempo Development is a nearshore software development company. Our headquarters are in AZ, but we are a pioneer and leader in outsourcing to Mexico, based on our three software development centers there. We have a proven process and we are experts at providing our customers with powerful solutions. We transform ideas into reality.

When individual departments procure cloud service for their own use, they usually don't consider the hazardous organization-wide implications. Read this paper to learn best practices for setting up an internal, IT-based cloud brokerage function that service the entire organization. Find out how this approach enables you to retain top-down visibility and control of network security and manage the impact of cloud traffic on your WAN.