Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Generics Converter for Basic Types

0.00/5 (No votes)
18 Jun 2010 1  
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 has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here