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

Generics Converter for Basic Types

, 17 Jun 2010 CPOL
Rate this:
Please Sign up or sign in to vote.
A generics method to convert an object to a basic type.

Screenshot.jpg

Introduction

This article presents a possibility to create a generics conversion method which can be used by the basic types (bool, int, byte, etc.).

Background

There are cases where you want to create generic processing for several different data types which are very similar but don't have a common parent class or don't inherit a common interface. This is very often the case with the basic .NET classes that represent the value types bool, int, byte, etc. Although they are all value types, they don't have a common parent that has any useful methods.

A simple example given here: you want to provide the user with several text boxes where he/she can enter a value that needs to be tested. This is very easy to do by just coding a different method for each value type like this:

private void TestInt32(TextBox textBox, Label resultLabel)
{
    try
    {
        Int32 res = Convert.ToInt32(textBox.Text);
        resultLabel.Text = "Success!";
        resultLabel.BackColor = Color.Green;
    }
    catch
    {
        resultLabel.Text = "Failure!";
        resultLabel.BackColor = Color.Red;
    }
}
    
private void TestBool(TextBox textBox, Label resultLabel)
{
    try
    {
        Boolean res = Convert.ToBoolean(textBox.Text);
        resultLabel.Text = "Success!";
        resultLabel.BackColor = Color.Green;
    }
    catch
    {
        resultLabel.Text = "Failure!";
        resultLabel.BackColor = Color.Red;
    }
}

This is both annoying and repeating a lot of code to do the same. Unfortunately, Microsoft did not provide us with a way to write a generics class/method for the basic value types. This article shows a possible solution.

Using the Code

The example code shows a generics method for conversion of an object to a provided basic value type.

public static T ToT<T>(object value)
{
    switch (Type.GetTypeCode(typeof(T)))
    {
        case TypeCode.Boolean:
            return (T)(object)Convert.ToBoolean(value);
        case TypeCode.Byte:
            return (T)(object)Convert.ToByte(value);
        case TypeCode.Char:
            return (T)(object)Convert.ToChar(value);
        case TypeCode.DateTime:
            return (T)(object)Convert.ToDateTime(value);
        case TypeCode.Decimal:
            return (T)(object)Convert.ToDecimal(value);
        case TypeCode.Double:
            return (T)(object)Convert.ToDouble(value);
        case TypeCode.Int16:
            return (T)(object)Convert.ToInt16(value);
        case TypeCode.Int32:
            return (T)(object)Convert.ToInt32(value);
        case TypeCode.Int64:
            return (T)(object)Convert.ToInt64(value);
        case TypeCode.Object:
            return (T)value;
        case TypeCode.SByte:
            return (T)(object)Convert.ToSByte(value);
        case TypeCode.Single:
            return (T)(object)Convert.ToSingle(value);
        case TypeCode.String:
            return (T)(object)Convert.ToString(value);
        case TypeCode.UInt16:
            return (T)(object)Convert.ToUInt16(value);
        case TypeCode.UInt32:
            return (T)(object)Convert.ToUInt32(value);
        case TypeCode.UInt64:
            return (T)(object)Convert.ToUInt64(value);
        case TypeCode.DBNull:
        case TypeCode.Empty:
        default:
            throw new ApplicationException("Unsupported generics type");
    }
}

The double conversion to object and then to T in every return is unfortunately unavoidable because Visual Studio cannot identify at compile time that the result of the conversion is of type T.

Thus a single method can be used to verify all our fields:

private void Test<T>(TextBox textBox, Label resultLabel)
{
    try
    {
        T res = ConvertEx.ToT<T>(textBox.Text);
        resultLabel.Text = "Success!";
        resultLabel.BackColor = Color.Green;
    }
    catch
    {
        resultLabel.Text = "Failure!";
        resultLabel.BackColor = Color.Red;
    }
}
private void testButton_Click(object sender, EventArgs e)
{
    Test<Int32>(this.int32TextBox, this.int32ResultLabel);
    Test<Boolean>(this.boolTextBox, this.boolResultLabel);
    Test<Decimal>(this.decimalTextBox, this.decimalResultLabel);
}

Further Development

Conversion is not the only operation that one would need for basic value types. For example, general Parse or TryParse methods would be very helpful and are pretty easy to implement in the same way.

Gratitude

I would like to specially thank Dobby who helped me with the consideration of this method and helped me make it clearer and easier to understand.

License

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

Share

About the Author

TheAvenger

Switzerland Switzerland
No Biography provided

Comments and Discussions

 
GeneralMy vote of 1 PinmemberWesley Brown18-Jun-10 4:24 
GeneralMy vote of 1 PinmemberMattia Baldinger18-Jun-10 2:00 
GeneralChangeType PinmvpPIEBALDconsult17-Jun-10 17:21 
Have you considered something like this:
 
        private static T
        ChangeType<T>
        ( 
            object o 
        )
        {
            return
            (
                (T) System.Convert.ChangeType
                (
                    o
                ,    
                    typeof(T)   
                )
            ) ;
        }

Generaltry catch vs TryParse Pinmemberrobert w. mcbean17-Jun-10 12:44 
GeneralRe: try catch vs TryParse PinmemberTheAvenger17-Jun-10 20:29 
GeneralGreat article Pinmembervbfengshui17-Jun-10 11:02 

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
Web04 | 2.8.141029.1 | Last Updated 18 Jun 2010
Article Copyright 2010 by TheAvenger
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid