The Graph Theory in C# (Part 5)

The Vertex is a class that has properties ID and Value. Both ID and Value must be set. This posed a problem because, in the real world, not everything has an ID. It should be possible to create a Vertex with both ID and Value available. However, it should also be possible to create a Vertex with just the Value, the Vertex internally assigning it a virtual ID.

Expanding on the original Vertex code, we can add two constructors: one that can take in both ID and Value; and another one that can take in only a Value.

    public Vertex(int id, object value)
    {
        ID = id;
        Value = value;
        IDGenerator.Seed(id);
    }

    public Vertex(object value)
        : this(IDGenerator.Generate(), value)
    {
    }

This code adds two constructors to the class Vertex. It uses the IDGenerator... Wait... What?! Are you trying to be sneaky, Mendz?!! Where did that IDGenerator come from?!!!

When I was thinking about this, I wondered if I should create a distinct class called IDGenerator, which can be used anywhere I need to generate IDs. That idea actually was not bad at all if you think about it yourself. However, I thought it would be better to make the IDGenerator internal to the Vertex, where I can give it Vertex specific awareness, interactions and features. This is really a personal design choice and I encourage developers to choose the approach they are more comfortable with in this regard.

public class Vertex
{

    ...

    public static class IDGenerator
    {
        private static int _id = 0;

        public static void Seed(int seed)
        {
           if (_id < seed)
           {
              _id = seed;
           }
        }

        public static int Generate()
        {
           return ++_id;
        }
    }
}

This code adds a static class IDGenerator inside the Vertex. A class inside a class? Yes, it's possible! The IDGenerator's main method is of course the ability to Generate() an ID. I added the Seed() method to let developers set or initialize the IDGenerator's internal incrementation. This is handy when the values are a mix of those with IDs and those with none: the former's maximum ID + 1 can easily be the latter's starting ID and continue incrementing from there.

Since the ID is intended to store and communicate identity, equality operations with the Vertex should use the ID. Two persons named John Smith with different IDs are not the same John Smiths, right? To make sure that the Vertex behaves this way, I added overrides to the base object's Equals() and GetHashCode() methods. Below is the completed code in full.

Vertex.cs
namespace Mendz.Graphs
{
    public class Vertex
    {
        public int ID { get; private set; }
        public object Value { get; set; }

        public Vertex(int id, object value)
        {
            ID = id;
            Value = value;
            IDGenerator.Seed(id);
        }

        public Vertex(object value)
            : this(IDGenerator.Generate(), value)
        {
        }

        public override bool Equals(object obj)
        {
            if (obj == null || !(obj is Vertex))
            {
                return false;
            }
            return ID == ((Vertex)obj).ID;
        }

        public override int GetHashCode()
        {
            return ID;
        }

        public static class IDGenerator
        {
            private static int _id = 0;

            public static void Seed(int seed)
            {
                if (_id < seed)
                {
                    _id = seed;
                }
            }

            public static int Generate()
            {
                return ++_id;
            }
        }
    }
}

For those in the know, testing the Vertex's equality using only the ID is debatable. I keep it here as a feature knowing that it can also be a limitation. The plain reason I can't compare with Value is because it is an object type. My Vertex can only see the Value as an object instance, nothing more. Testing its equality without knowing exactly what kind of object it is beyond what the Vertex knows can't be reliable. This is very much unlike ID which is a primitive type int. In C#, int's test for equality is absolute and certain. If you read this far, you're probably a programmer yourself. I'd leave it to you and developers like you to expand on this area. As far as I am concerned, my Vertex class is done.

Comments