stockxpertcom_id14589271_jpg_013ced4118ce4854e1935aeaa12684ecThis is another one of of my topics which I deem to be Tribal Knowledge type information. For me it seems that such information seems be known by only the privileged few. In this article I present for your reading perusal details on how to handle different state errors found in classes and arguments during debug/development activities. The premise is that such checks for object or argument correctness is only needed for development and not for production level code. By using the Conditional attribute in ones C# code such checks can be utilized for object and state correctness but not be a burden in a production program or web site.

Development State Errors Checking

For example, and yes its a basic example,  say one is writing a database layer and the requirement is that the connection string be be properly filled with with a database name a user name and a password. You happen to know that this code will be reused by others on the development staff and they will most likely fail to provide such values the first time they hook up the code. So you don’t have to go to their desks to hand hold and debug the error, wouldn’t it be nice if the object checked its own state of correctness?

Once working the checks will really become superfluous and will be removed. This scenario speaks to the fact that the user has two options, or two roads to failure, of loading the values. Say it can be done either during construction or after via the exposed properties. Just ripe for someone to forget to do one or the other.

Code Speaks Conditionally

For the code we will create a connection object which checks for the validity, to the best of its ability, of those values before their use, and if a problem exists throw an application exception during development time only.

Here is our code and the highlight lines are related to the state checking:

using System.Diagnostics;

public class ConnectionManager
{
    public string DatabaseName { get; set; }
    public string UserName     { get; set; }
    public string Password     { get; set; }

    public ConnectionManager() { }

    public ConnectionManager( string databaseName, string userName, string password )
    {
        DatabaseName = databaseName; UserName = userName; Password = password;
    }

    public string GenerateConnectionString()
    {
        // This is only called during debug builds and *not compiled*
        ValidateState(); // during Release builds.

        return string.Format( "{0};User={1};Password={2}", DatabaseName, UserName, Password );
    }

    [Conditional( "Debug" )]
    private void ValidateState()
    {
        if ( string.IsNullOrEmpty( DatabaseName ) )
            throw new ApplicationException( "Development Error: DatabaseName Empty" );

        if ( string.IsNullOrEmpty( UserName ) )
            throw new ApplicationException( "Development Error: UserName Empty" );

        if ( string.IsNullOrEmpty( Password ) )
            throw new ApplicationException( "Development Error: Password Empty" );

    }

}

So if this class is instantiated and the proper variables are not setup an application exception is thrown during debug mode only when a call to generate a connection string occurs. The magic is done by the highlighted lines but the second one with Conditional attribute tells the compiler to only use this in debug builds

Summary

Now this example is a bit contrived, but the idea is that if one has unique business state requirements which may need to be met before an object’s operation can be used, this methodology can be used to catch all actions, but not hamper runtime operations. It obviously shouldn’t be used to catch unique runtime scenarios such as user validation, those should be handled directly and possibly not by generating an exception.

Share