编程语言
首页 > 编程语言> > c# – 取消装箱-1并使用泛型强制转换为Nullable会产生InvalidCastException

c# – 取消装箱-1并使用泛型强制转换为Nullable会产生InvalidCastException

作者:互联网

this SO post中,我找到了一个通用扩展方法,如果SqlDataReader读取的值为null或DBNull.Value,则返回默认值,否则返回正确转换的值.我这样实现了:

public static T GetValueOrDefault<T>(this SqlDataReader reader, string columnName, T defaultValue = default(T))
{
  object val = reader[columnName];
  if (val == null || val == DBNull.Value)
  {
    return defaultValue;
  }

  return (T)val;
}

下面提到的上面提到的帖子中的方法没有使用正确的语法,但是仍然建议这也适用于可以为空的类型,例如int?.

但是,我从数据库中读取了一个可以为空的int列,如下所示:

MyProperty = reader.GetValueOrDefault<int?>("SomeColumnName")

调试模式显示val是-1并且T是int ?,但是我得到InvalidCastException.从this post开始,我认为这是因为拆箱和铸造不能在一次操作中执行(val是具有短值的对象类型),但是我能做些什么来使它在我的情况下工作?由于它是一种通用方法,我不知道在进行转换之前如何手动取消它.

解决方法:

要获得非常好的答案,您需要发布a good, minimal, complete code example.

如果转换为int失败,则盒装值不是int.您应该能够在调试器中看到它实际上是什么.

也就是说,Convert类在转换方面要复杂得多;演员表需要完全匹配,即盒装值必须是int(文字-1将是一个int,但在你的情况下,值来自who-know-where,很容易可能是short或long或者其他) .

所以不是演员,而是一个电话,例如转换为.ToInt32()会更好.

在您的情况下,使用泛型方法(即在编译时类型未知),Convert.ChangeType()方法可能更合适:

public static T GetValueOrDefault<T>(this SqlDataReader reader, string columnName, T defaultValue = default(T))
{
  object val = reader[columnName];
  if (val == null || val == DBNull.Value)
  {
    return defaultValue;
  }

  return (T)Convert.ChangeType(val, typeof(T));
}

标签:c,casting,unboxing,generics
来源: https://codeday.me/bug/20190609/1205061.html