When inputting data from an external source (like a file),
it is up to the component to interpret the data type of the content. For
instance, in a database system, the data types of each data in .NET have a
mapping to their SQL Server or Oracle database equivalent.
When reading data from a component (stream reader or data
table), the data that comes into the system may be the value 1. Although it is
a number, the underlying data type could be a string, so "1" does not
equal 1. Instead, to get the "1" to the correct type, the int.Parse
or int.TryParse method has to convert the value correctly. But in developing a
generic solution for all of these possible types, this is the purpose of this
article.
Sometimes there is a table that has data using many
different types (like the profile table), where all these values are stored in
an nvarchar or varchar database column. Because the underlying .NET type is
string, these values cannot simply be cast to a DateTime or int. This would
cause an exception; what is required is to use DateTime.Parse or int.Parse, as
long as the value is valid (then TryParse can be used to protect against this).
To perform the type conversion, I have used a helper method
to convert the values accordingly. For instance, suppose you are using a key
to retrieve an item from an underlying collection (that may have been populated
from a file or database), the following approach can be used to dynamically
convert the data to a generic type that meets the following signature.
Listing 1
private T GetValue<T>(string key) { }
After getting a value from a collection, the first check
ensures that the data is not null or equal to a database null. If it is one of
these values, default(T) is returned. This statement returns the default value
for the specified type as a safeguard. For reference types, null is returned.
For value types, the minimum value is returned (integer returns 0).
The next processing step is if the underlying value is the
designated type. If the value matches the generic type exactly, it is returned
as is.
Listing 2
if (value is T) return (T)value;
When returning a generic type, sometimes the user wants a
string, regardless of whether the underlying implementation is an int, decimal,
DateTime, etc. A little trick to bypass a compiler error is shown below. You
cannot simply call ToString() and return that value. Even though the types
match in your logic, the compiler does not know that this condition will always
be a string because it is solely dealing with a generic type T, and not the
underlying representation.
Listing 3
//If the type of T is a string type, then process this
object stringValue = value.ToString();
return (T)stringValue;
For all convertible types, the type of an object can be
converted using Convert.Change type. Most DateTime, string, and most value
types support using Convert.ChangeType to change the underlying implementation.
However, make sure that the type is convertible first before you call it,
because an exception will be thrown if it is not (which may be good or bad
depending on the situation).
I found one variance from this approach: nullable types. Nullable
types do not support conversion using Convert.ChangeType, and I came up with a
workaround below.