相关疑难解决方法(0)

检查DBNull然后分配给变量的最有效方法是什么?

这个问题偶尔出现,但我没有看到一个满意的答案.

典型的模式是(row是DataRow):

 if (row["value"] != DBNull.Value)
 {
      someObject.Member = row["value"];
 }
Run Code Online (Sandbox Code Playgroud)

我的第一个问题是哪个更有效率(我翻了条件):

  row["value"] == DBNull.Value; // Or
  row["value"] is DBNull; // Or
  row["value"].GetType() == typeof(DBNull) // Or... any suggestions?
Run Code Online (Sandbox Code Playgroud)

表明.GetType()应该更快,但编译器可能知道一些我不知道的技巧?

第二个问题,是否值得缓存row ["value"]的值,或者编译器是否优化了索引器?

例如:

  object valueHolder;
  if (DBNull.Value == (valueHolder = row["value"])) {}
Run Code Online (Sandbox Code Playgroud)

笔记:

  1. row ["value"]存在.
  2. 我不知道列的列索引(因此列名称查找).
  3. 我具体要求检查DBNull然后分配(不是关于过早优化等).

我对几个场景进行了基准测试(时间以秒为单位,10,000,000次试验):

row["value"] == DBNull.Value: 00:00:01.5478995
row["value"] is DBNull: 00:00:01.6306578
row["value"].GetType() == typeof(DBNull): 00:00:02.0138757
Run Code Online (Sandbox Code Playgroud)

Object.ReferenceEquals与"=="具有相同的性能

最有趣的结果?如果您不匹配逐列的名称(例如,"值"而不是"值",则大约需要十倍的时间(对于字符串):

row["Value"] == DBNull.Value: 00:00:12.2792374
Run Code Online (Sandbox Code Playgroud)

故事的寓意似乎是,如果您无法通过索引查找列,请确保您提供给索引器的列名称与DataColumn的名称完全匹配.

缓存该值似乎也几乎快了两倍:

No Caching: 00:00:03.0996622
With Caching: 00:00:01.5659920
Run Code Online (Sandbox Code Playgroud)

所以最有效的方法 …

.net dbnull

150
推荐指数
9
解决办法
16万
查看次数

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

该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值的类型),但是我能做些什么来使它在我的情况下工作?由于它是一种通用方法,我不知道在进行转换之前如何手动取消它.

c# generics unboxing casting

4
推荐指数
1
解决办法
92
查看次数

标签 统计

.net ×1

c# ×1

casting ×1

dbnull ×1

generics ×1

unboxing ×1