I am stuck with some old API that involves COM and ODBC, and I cannot switch to cool things like MEF or entity framework. So, I am working on some wrappers that will help me write less code and also bring some of the type safety back (as you know, COM and SQL do not have type safety, at least not in the same way as C# does).The goal is that I want to be able to write things likeint? orderId = sqlHelper.GetOrderId(...some arguments that will help the where clause...)andList<int> goodOrderIds = sqlHelper.GetGoodOrderIds(...)andList<int?> orderId = activeReport.GetGoodSelectedOrderIds()where activeReport is a home-brewed GUI grid, which may or may not have a column named order_id, and if it does, then some rows of the GUI report may still have null values. Here is an extension class for the GUI report. I have two TODO comments that I would like you to address:public static class ReportExtensions{    public static IList<object> GetSelectedFieldValues(this Report activeReport, string fieldName)    {        // Implementation hidden. May return at least some null values.        return result;    }    public static IList<T> GetSelectedFieldValues<T>(this Report activeReport, string fieldName)        where T : struct, IConvertible    {        // This smells like a maybe monad; I wish I got Haskell.        // TODO: See if this can be simplified.        return activeReport.GetSelectedFieldValues(fieldName)            .Select(value => GenericConverter.To<T>(value))            .Where(nullable => nullable.HasValue)            .Select(nullable => nullable.Value)            .ToList();    }    public static IList<string> GetSelectedStringFields(this Report activeReport, string fieldName)    {        // TODO: Is this LINQ query in its simplest form?        return activeReport.GetSelectedFieldValues(fieldName)            .Select(value => GenericConverter.ToString(value))            .Where(str => str != null)            .ToList();    }}And here is my GenericConverter class, which allows converting an object to a given simple type, if it can. I introduced the private static IConvertible ConvertTo<T>(object value) method in order to appease the compiler. As I understand, generic types can be restricted to some interface or a subclass in a hierarchy, but I do not think I can say something likewhere T in (int, short, ... double, DateTime, string), which is what I would ultimately like to do, if I could. One alternative would be to create my own NullableConvert class and implement methods such as decimal?ToDecimal(object value)`but I do not like having to type all that stuff in. For instance, having to return null on cast failure would require a try/catch or other code inside the body of every method./// <summary>/// This class helps to convert from any object to an IConvertible if possible./// This is convinient to use with the SqlHelper, ReportHelper class./// This class does not convert everything imaginable, but it does support the standard IConvertible./// </summary>public static class GenericConverter{    public static bool IsNullValue(object value)    {        return (value == null || value == DBNull.Value);    }    public static string ToString(object value)    {        if (IsNullValue(value))        {            return null;        }        return Convert.ToString(value);    }    public static T? To<T>(object value)        where T : struct, IConvertible    {        var result = ConvertTo<T>(value);        if (result == null)        {            return null;        }        return (T)result;    }     // http://msdn.microsoft.com/en-us/library/system.iconvertible.aspx    // Boolean, SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Single, Double, Decimal, DateTime, Char    private static IConvertible ConvertTo<T>(object value, bool nullOnCastException = false)        where T : struct, IConvertible    {        if (IsNullValue(value))        {            return null;        }        try        {            if (typeof(T) == typeof(bool))            {                return Convert.ToBoolean(value);            }            if (typeof(T) == typeof(sbyte))            {                return Convert.ToSByte(value);            }            if (typeof(T) == typeof(byte))            {                return Convert.ToByte(value);            }            if (typeof(T) == typeof(char))            {                return Convert.ToChar(value);            }            if (typeof(T) == typeof(short))            {                return Convert.ToInt16(value);            }            if (typeof(T) == typeof(ushort))            {                return Convert.ToUInt16(value);            }            if (typeof(T) == typeof(int))            {                return Convert.ToInt32(value);            }            if (typeof(T) == typeof(uint))            {                return Convert.ToUInt32(value);            }            if (typeof(T) == typeof(long))            {                return Convert.ToInt64(value);            }            if (typeof(T) == typeof(ulong))            {                return Convert.ToUInt64(value);            }            if (typeof(T) == typeof(float))            {                return Convert.ToSingle(value);            }            if (typeof(T) == typeof(double))            {                return Convert.ToDouble(value);            }            if (typeof(T) == typeof(decimal))            {                return Convert.ToDecimal(value);            }            if (typeof(T) == typeof(DateTime))            {                return Convert.ToDateTime(value);            }            // I never trully intended to work with everything that implements IConvertible.            // I just wanted             string fromTypeName = value.GetType().FullName;            string toTypeName = typeof(T).FullName;            string exceptionMessage = String.Format(                Unable to convert a value '{0}' of type '{1}' to type '{2}'.,                value,                fromTypeName,                toTypeName);            throw new InvalidCastException(message: exceptionMessage);        }        catch // Perhaps restrict these only to the exception types that pertain to casting only. How do I find the exhaustive list though? C# does not have checked exceptions like Java does.        {            if (nullOnCastException)            {                return null;            }            throw;        }    }}
Using strong types on top of COM and ODBC
c#;linq;converting
I believe you can shorten this by using Convert.ChangeType. Also I altered your catch to handle only InvalidCastException since the name of your bool argument is quite specific. You may want to consider how you'll handle FormatException and OverflowException.private static IConvertible ConvertTo<T>(object value, bool nullOnCastException = false)    where T : struct, IConvertible{    if (IsNullValue(value))    {        return null;    }    try    {        return (T)Convert.ChangeType(value, typeof(T));    }    catch (InvalidCastException)    {        if (nullOnCastException)        {            return null;        }        throw;    }}}