取消装箱-1并使用泛型强制转换为Nullable <int>会产生InvalidCastException

时间:2015-04-27 08:15:24

标签: c# generics casting unboxing

resizeterm中,我找到了一个通用扩展方法,如果SqlDataReader读取的值为nullDBNull.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-1Tint?,但我收到InvalidCastException。从this SO post开始,我认为这是因为无法在单个操作中执行取消装箱和转换(val属于object类型,持有short值,但我能做些什么做到在我的情况下工作?由于它是一种通用方法,我不知道在进行转换之前如何手动取消它。

1 个答案:

答案 0 :(得分:5)

要获得真正好的答案,您需要发布a good, minimal, complete code example

如果转化为int失败,则框内值不是int。您应该能够在调试器中看到它实际上是什么。

也就是说,Convert课程在转化方面要复杂得多;演员表需要完全匹配,即盒装值必须为int(文字-1int,但在您的情况下,值为& #39; s来自who-know-where,很容易成为shortlong或其他任何内容。

所以不是演员,而是一个电话,例如到Convert.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));
}