Click here to Skip to main content
Click here to Skip to main content

State Checking Objects

, 20 Aug 2012
Rate this:
Please Sign up or sign in to vote.
This is a generic wrapper class to monitor and fix the internal state of its value.

Introduction

While learning the Nullable<T> class, I found the same logic can be used to create objects which have the capability to check its internal state itself and correct if it is invalid. The Nullable class is just a wrapper class to keep a generic type value internally. So I decided to create a generic wrapper class to monitor its internal value.

Using the Code

Below is the complete code for StateCheck class.

public class StateCheck<T>
{
    private T value;
    private DefaultValueAction DefaultValue;
    private CheckStateAction CheckState;

    public delegate T DefaultValueAction(T current,T previous);
    public delegate bool CheckStateAction(T current, T previous);

    public StateCheck(CheckStateAction checkState, DefaultValueAction defaultValue)
    {
        CheckState = checkState;
        DefaultValue = defaultValue;
    }

    public T Value()
    {
        return value;
    }

    public void Value(T val)
    {
        value = !CheckState(val, value) ? DefaultValue(val, value) : val;
    }
}

The StateCheck class is a simple generic class which accepts any data types as its generic type. There is a private variable named value which is used to store the actual value of the generic type. The class has only one parameterized constructor which accepts two functions as its parameters. These functions have a key role on this logic. The user can define both of these functions at the time of object creation.

Both functions can access the previous value (the value already assigned to the value variable) and new incoming value as parameters. The first function is a validation function which may return false if the new incoming value is invalid. If the validation function returns false, then the second function will execute. The purpose of this function is to provide a default value and prevent the object from being in an invalid state. These functions give flexibility to the developers to define the behavior of an individual instance of StateCheck class whenever it meets an invalid value. It is impossible to declare a StateCheck class object without specifying both the functions. This will ensure the functions are available before assigning any values.

The remaining two overloaded public functions are used to get and set the value. The parameter less Value function simply returns the value. The second function used to set the value. This function contains the logic which makes sure the StateCheck class object doesn’t accept any invalid values. Before assigning, it will check whether the input is invalid. If it is invalid, the DefaultValue delegate will be executed.

Now we will check how to use this class. To do this, just create a console application and copy the code below in to the main function.

StateCheck<string> str = new StateCheck<string>(
                (current, previous) => { return current != null; },
                (current, previous) => { return "EMPTY"; });

str.Value("test string");
Console.WriteLine(str.Value());
str.Value(null);
Console.WriteLine(str.Value());

The str variable is designed to fill with the word “EMPTY” when it is assigned with a null value. In the beginning, the variable assigned with the string “test string”. This is a valid string based on the condition we given at the time of object creation. So it will return the same when Console.WriteLine first time tried to fetch the value. In the next step, the variable assigned with a null value which is an invalid string based on our definition. So when the second time Console.WriteLine tried to fetch the value, the variable return the default value (“EMPTY”).

Null object pattern

The Null object pattern is a design pattern to avoid null objects. The core idea behind this design pattern is that to use a dummy object instead of a null value. So whenever developer wants to assign a null value into the object, they will assign a dummy object instead. While using Null object pattern, the developer must ensure to create the dummy object whenever there is a null value. How we can prevent an object is being assigned with a null value accidently instead of the dummy object? We can solve this issue using our StateCheck class. Here is the Wikipedia link if you want to know more about Null object pattern. Below code is using the C# implementation of Null object pattern described in the above Wikipedia link.

To create the object of IAnimal, we can use StateCheck class as below.

StateCheck<IAnimal> animal = new StateCheck<IAnimal>(
                (current, previous) => { return current != null; },
                (current, previous) => { return new NullAnimal(); });

So whenever the animal object assigns with a null value, the StateCheck wrapper class will ensure it will assign the NullAnimal object instead. This will reduce the burden to ensure the object is not assigned with a null from anywhere in the program.

Advantages

You can avoid all the validation checks whether the object is in an invalid state. The Value function is always grantee to return a valid data of the type T.

Drawbacks

The State checking wrapper class has its own drawbacks. Use it in only the places where you really want it. You should have few things in mind while using this.

  1. It requires memory - The additional wrapper class instance for every variable need additional memory.
  2. The main use of this method may avoid the null values. But the null values aren’t that evil. It has some specific purpose and meaning. The presence of null value should be handled. Sometimes hiding a null reference exception and continue program execution will cause unpredictable results on application.
  3. What if the developer returns an invalid value from the default value delegated function? It is almost impossible to validate this. So I leave this risk to the developers.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Kannan Ar
Software Developer (Senior)
India India
No Biography provided

Comments and Discussions

 
QuestionWhy Value() method? PinmvpPaulo Zemek23-Aug-12 7:02 
AnswerRe: Why Value() method? PinmemberKannan Ar23-Aug-12 14:08 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140721.1 | Last Updated 20 Aug 2012
Article Copyright 2012 by Kannan Ar
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid