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

Inv*_*nda 4 c# generics unboxing casting

该SO交我发现它返回一个默认值,如果由读出的值的通用扩展方法SqlDataReadernullDBNull.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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

MyProperty = reader.GetValueOrDefault<int?>("SomeColumnName")
Run Code Online (Sandbox Code Playgroud)

其中,调试模式让我发现,val-1Tint?,但我得到一个InvalidCastException.从这篇文章中我发现这是因为拆箱和铸造不能在一次操作中执行(val具有object保持short值的类型),但是我能做些什么来使它在我的情况下工作?由于它是一种通用方法,我不知道在进行转换之前如何手动取消它.

Pet*_*iho 5

要获得一个非常好的答案,您需要发布一个好的,最小的,完整的代码示例.

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

也就是说,Convert关于转换,课程要复杂得多; 剧组将需要一个精确的匹配,即装箱的值必须是int(字面-1将是一个int,但在你的情况下,值的来自哪里谁也不知道的地方,轻松地可以是一个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));
}
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案,但我不认为`-1`可以是一个'uint`.:) (3认同)