在泛型方法中的一个语句中拆箱和强制转换

本文关键字:转换 语句 泛型方法 一个 | 更新日期: 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;
}

在我的特定场景中,我从数据表中取出一条记录,并使用弱类型从中取出特定字段,并且我得到的特定字段是被装箱成objectlong。下面是一个复制此操作的示例:

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);
}