我有一个小实用方法,如下所示:
/// <summary>
/// Replaces a DBNull value with the default of the type specified
/// </summary>
/// <typeparam name="T">Resulting type</typeparam>
/// <param name="p_this">Object to check for DBNull</param>
/// <returns>p_this if it is not DBNull.Value, else default(T)</returns>
public static T ReplaceDBNullWithDefault<T>(this object p_this)
{
return p_this == System.DBNull.Value ? default(T) : (T)p_this;
}
在我的特定场景中,我正在从数据表中取出记录并使用弱类型从中获取特定字段,而我获得的特定字段是long
正在盒装成object
。重现这一点的一个例子如下:
var obj = 2934L;
int num = obj.ReplaceDBNullWithDefault<int>();
在InvalidCastException
处(T)p_this
失败。
我明白为什么,盒装的long
无法直接投放到int
,尝试这样做也会失败:
object myLong = 234L;
int myInt = (int)myLong;
然而,拆箱然后转换工作正常:
object myLong = 234L;
int myInt = (int)(long)myLong;
我如何在我的方法中解决这个问题?
答案 0 :(得分:0)
你可以试试这个:
public static T ReplaceDBNullWithDefault<T>(this object p_this) where T : struct
{
return
p_this == System.DBNull.Value
? default(T)
: (T)Convert.ChangeType(p_this, typeof(T));
}
但是,如果您尝试将此函数应用于不可转换类型,则会出现异常。
因此,将值手动转换为已知类型可能会更好。
答案 1 :(得分:0)
您可以使用此方法:
/// <summary>
/// Replaces a DBNull value with the default of the type specified
/// </summary>
/// <typeparam name="T">Resulting type</typeparam>
/// <param name="value">Object to check for DBNull</param>
/// <param name="tryConvert">if true the object will be converted to the target type if possible, otherwise an InvalidCastException is raised</param>
/// <returns>p_this if it is not DBNull.Value, else default(T)</returns>
/// <exception cref="InvalidCastException">Thrown if the target type is incorrect and the value could not be converted to it</exception>
public static T ReplaceDbNullWithDefault<T>(this object value, bool tryConvert = true)
{
if (value == System.DBNull.Value || value == null)
return default(T);
if (value is T)
return (T) value;
if(!tryConvert || !(value is IConvertible))
throw new InvalidCastException($"Cannot convert {value.GetType()} to {typeof(T)}.");
return (T)((IConvertible) value).ToType(typeof(T), null);
}