在泛型方法中的一个语句中拆箱和强制转换
本文关键字:转换 语句 泛型方法 一个 | 更新日期: 2023-09-27 18:08:12
我有一个小的实用程序方法,看起来像这样:
/// <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;
}
在我的特定场景中,我从数据表中取出一条记录,并使用弱类型从中取出特定字段,并且我得到的特定字段是被装箱成object
的long
。下面是一个复制此操作的示例:
var obj = 2934L;
int num = obj.ReplaceDBNullWithDefault<int>();
在(T)p_this
处,InvalidCastException
失效
我明白为什么,盒装的long
不能直接转换为int
,并且试图这样做也失败了:
object myLong = 234L;
int myInt = (int)myLong;
但是,拆箱然后强制转换工作得很好:
object myLong = 234L;
int myInt = (int)(long)myLong;
我如何在我的方法中解决这个问题?
你可以试试:
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));
}
然而,如果您尝试将此函数应用于不可转换类型,则会得到异常。
所以可能最好手动将值转换为已知的类型
您可以使用这种方法:
/// <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);
}