Enum Polymorphism

There are times in code when you if available, enum polymorphism would be great. To help explain what I mean by this, consider the following scenerio.

Let’s define a simple library that allows a client to read and write strings to addresses. Some of these addresses are read only, whilst others may be both read and written.

public enum Address : byte
{
    // A read-only serial number (read)
    SerialNumber = 0x01,

    // A user-defined name (read and write).
    Name = 0x02
}

public static string Read(Address address);
public static void Write(Address address, string value);

Then a client can use this library as shown below.

static void Main(string[] args)
{
    // All good, can read from both addresses
    string serial_number = Read(Address.SerialNumber);
    string name = Read(Address.Name);

    // Good - can write to name address
    Write(Address.Name, "john smith");

    // BAD - run-time error!
    Write(Address.SerialNumber, "0123456789");
}

 

Run-Time vs Compile-Time Errors

This program will compile successfully, but will fail at run-time (when we attempt to write to the SerialNumber address). Instead, it would be better if we could force the compiler to help us find these errors.

For this simple scenerio, a simple code review may have discovered the error. But as the code expands, or other clients use the library, the error may not be so easily detected.

The question is, is it possible to design a better library to help the client discover these errors at run-time?

The answer is Yes.

Enum Polymorphism

If enum polymorphism was available, this would be simply solved by:

public enum AddressRead : byte
{
    // A read-only serial number
    SerialNumber = 0x01,
}

public enum AddressWrite : AddressRead
{
    // A user-defined name (read and write).
    Name = 0x02
}

public static string Read(AddressRead address);
public static void Write(AddressWrite address, string value);

This library now ensures that only addresses that are AddressWrite can be written to; and both the AddressRead and AddressWrite can be read.

Currently, the C-Sharp language does not support this concept of enum polymorphism… but let’s not let that stop us.

This code can be easily changed to work within the constraints of the C-Sharp language, and provide the compile-time support we endevour to seek.

Enum Polymorphism – written with classes

Below is the new library written using classes to define the types of available addresses; and a static class to hold all the enumerations.

public static class Address
{
    public static readonly AddressRead SerialNumber = new AddressRead(0x01);
    public static readonly AddressReadAndWrite Name = new AddressReadAndWrite(0x02);
}

public class AddressRead : byte
{
    public AddressRead(byte value)
    {
        this.Value = value;
    }
    public byte Value { get; private set; }
}

public class AddressReadAndWrite : AddressRead
{
    public AddressReadAndWrite(byte value)
        : base(value)
    {
    }
}

public static string Read(AddressRead address);
public static void Write(AddressReadAndWrite address, string value);

Now, for the given client code …

static void Main(string[] args)
{
    // All good, can read from both addresses
    string serial_number = Read(Address.SerialNumber);
    string name = Read(Address.Name);

    // Good - can write to name address
    Write(Address.Name, "john smith");

    // COMPILE-TIME ERROR !
    // Argument 1: cannot convert from 'Program.AddressRead'
    // to 'Program.AddressReadAndWrite'
    Write(Address.SerialNumber, "0123456789");
}

The code will now correctly fail at compile time.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>