Using Objects Instead of Enumerations
page 3 of 4
by Brendan Enrick
Feedback
Average Rating: 
Views (Total / Last 10 Days): 23917/ 59

Creating an Object-based Solution

What are the properties of enumerations we want to be able to replicate?

·         Strongly typed access

·         Unchanging at runtime

·         Name and value pairing

·         Customizable values

·         Conversion to integers

·         Get by value

·         Get by name

·         List all

So in order to replace our enumeration we are going to need to include these. Since we are using objects, the first one should be easily done. Our object will need to have at least two properties for the Name and the Value. So if we were just going to create a regular object we would have something like this.

Listing 3: Normal Object

public class MyObject
{
  public int Id { get; set; }
  public string Name { get; set; }
}

With this object we could create instances of it at runtime, but this is not what we want yet. The next step is making sure that we have a set of instances to start with and no more can be created. To do this we will make out constructor private. With the constructor private, we will need to declare the instances of this object inside the class, so the instances will need to be static. We will need to make sure that all of the values can be passed into the constructor so the instances can be created easily as static properties of the class This has the nice effect of allowing us to access them using ClassName.InstanceName. That naming convention will look similar to the one for enumerations which is Enumname.InstanceName.

Our new code which uses static instances and a private constructor looks like this.

Listing 4: Static Instances and Private Constructor

public class MyObject
{
    public static MyObject MyObjectOne = new MyObject(1, "MyObjectOne");
    public static MyObject MyObjectTwo = new MyObject(2, "MyObjectTwo");
    public static MyObject MyObjectThree = new MyObject(3, "MyObjectThree");
 
    public int Id { get; private set; }
    public string Name { get; private set; }
    
    private MyObject(int id, string name)
    {
        Id = id;
        Name = name;
    }
}

This object will already do a lot of what we need. It maintains a limited set, is strongly typed, has a name, has a value, you have control over the values for each, and the Id property lets you have it as an integer. Now we need to be able to get these based on the Id and the Name, and we also need to maintain a list of them.

Listing all of the values is useful for displaying them in different places such as a DropDownList or something similar.

Listing 5: Listing All of the Instances

public static List<MyObject> ListAll()
{
   return new List<MyObject>
  {
    MyObjectOne,
    MyObjectTwo,
    MyObjectThree
  };
}

For this it is pretty easy to just put them in a list like this or something similar. Not too difficult to maintain, it gives you good control of what is in the list.

Getting the instance of the object by Id and by Name is also pretty easy. With very little effort we are able to get them, and we throw some exceptions if we receive invalid method arguments.

Listing 6: FromId and FromName

public static MyObject FromId(int id)
{
    List<MyObject> items = ListAll();
    MyObject match = Array.Find(items.ToArray(), instance => instance.Id == id);
 
    if (match == null)
    {
        throw new ArgumentOutOfRangeException(string.Format(
            "Id '{0}' is invalid for {1}", id, typeof(MyObject).Name));
    }
 
    return match;
}
 
public static MyObject FromName(string name)
{
    List<MyObject> items = ListAll();
    MyObject match = Array.Find(items.ToArray(), instance => instance.Name == name);
 
    if (match == null)
    {
        throw new ArgumentOutOfRangeException(string.Format(
            "Name '{0}' is not a valid {1}", name, typeof(MyObject).Name));
    }
 
    return match;
}

At this point our object does pretty much everything we want it to do. This class is fairly testable, and is designed in such a way that we can add extra information to it. We can also add extra properties for any attributes we want like descriptions.


View Entire Article

User Comments

Title: good   
Name: msoni
Date: 2010-01-05 8:31:11 AM
Comment:
i like it ......its a very nice aricle
Title: Good Article/Weak Arguments   
Name: Clint
Date: 2009-03-25 2:13:49 PM
Comment:
Good article on the usage between objects/enumerators; weak arguments on the reasons. The statement "If there will be a good amount of logic based on these use an enumeration or an object. Do not have a lookup table. I know it is nice for the database, but any changes to the database will cause problems in the code." collapses on itself. Regardless of implementation, values that dictate logic will usually have a negative impact on the coded logic.
Title: Great!!!   
Name: Gourik Kumar Bora
Date: 2009-02-20 2:07:39 AM
Comment:
Hi Enrick!!!
This is really cool...
thanks a ton....
Title: Thanks   
Name: Amir Arjmand
Date: 2009-02-18 7:48:28 PM
Comment:
Thanks Brendan,

Yes it did answer my question.
Title: RE: Two questions   
Name: Brendan Enrick
Date: 2009-02-18 9:14:52 AM
Comment:
@Amir sorry about that. I am using a lambda expression in that code snippet.
http://msdn.microsoft.com/en-us/library/bb397687.aspx

Array.Find(items.ToArray(), instance => instance.Name == name);

Basically you can read this line like this, "find from items.ToArray() an item where that item's Name property is equal to the variable name".

The variable "instance" is defined at that point to represent any item in the array we are searching.

I hope that answers your questions.
Title: Two questions   
Name: Amir Arjmand
Date: 2009-02-17 9:54:41 PM
Comment:
Hi everyone, I am new to C# and as I was going through the sample code, I came upon this statement

instance => instance.Name == Name

Could anyone please explain how exactlly this part of the code works. Where does that instance come from and what is => ? I could not find anything regarding that operator in msdn library for C#?

Thanks;
Title: RE: hmm   
Name: Brendan Enrick
Date: 2009-02-17 8:50:19 AM
Comment:
@dario-g thank you for making sure I don't pass along misinformation. Although, there is a big difference between casting an integer as an enum and passing an out of range integer to this object. If you read the code listing 6 above, you will notice that the object throws an argument out of range exception if the integer is out of range. This means that you will know there is a problem and what the problem is. You can also easily handle this exception.

If you used the enum, you might not run into any exceptions, and maybe later the code will save the integer value of the enum. You are going to have an invalid result stored somewhere and possibly not even know.

Thank you for the comment. Feedback is always welcome and appreciated.
Title: Thank you   
Name: Brendan Enrick
Date: 2009-02-17 8:43:40 AM
Comment:
@Joydip Thank you. I am glad you liked the article.
Title: Mousover   
Name: Brendan Enrick
Date: 2009-02-17 8:42:47 AM
Comment:
@Alex Simkin Yes, you are right the debugger works very well with enumerations. However, if you move the mouse a little bit more to the plus sign, it will reveal the values of the properties of this object. This will give you access to not just the name, but also the value of the object. This is more than you would get from an enum.
Title: Mr. ?   
Name: Alex Simkin
Date: 2009-02-16 2:35:11 PM
Comment:
In debugger, if you mouseover variable of enum type, you will find out the value instantly. If you mouseover MyObject variable, you will only see that it contains MyObject instance.
Title: Author and ASP.NET MVP   
Name: Joydip Kanjilal
Date: 2009-02-16 10:59:03 AM
Comment:
Excellent article! Keep posting such awesome articles.

Thanks,

Joydip
Title: hmm   
Name: dario-g
Date: 2009-02-16 3:34:56 AM
Comment:
MyObject obj = ...FromId(10); // This is a really bad dangerous thing that can happen

No difference.






Community Advice: ASP | SQL | XML | Regular Expressions | Windows


©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-05-18 5:19:11 AM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search