【问题标题】:Single line if statement generates cast error单行 if 语句生成强制转换错误
【发布时间】:2012-03-04 16:33:17
【问题描述】:

C# 新手,所以我遇到了速记语句的问题。我要转换...

if (m_dtLastLogin == null)
    drow["LastLogin"] = DBNull.Value;
else
    drow["LastLogin"] = m_dtLastLogin;

drow["LastLogin"] = (m_dtLastLogin == null) ? System.DBNull.Value : m_dtLastLogin;

简写版本效果很好,但是简写版本会生成错误“无法确定条件类型,因为 'System.DBNull' 和 'System.DateTime?' 之间没有隐式转换”。我的支持代码基本上是……

private DateTime? m_dtLastLogin;
m_dtLastLogin = null;
DataRow drow;
drow = m_oDS.Tables["Users"].Rows[0];

有人可以帮我看看这里的速记吗?

【问题讨论】:

  • ?: 不是“单行 if”,它只是条件运算符。
  • ?: 必须在两种情况下返回相同的类型...
  • 顺便说一句:我会问m_dtLAstLogin.HasValue

标签: c# if-statement


【解决方案1】:

嗯,错误信息很清楚。编译器需要确定整个 x?y:z 表达式的类型。如果 y 和 z 具有相同的类型,则很容易。如果 y 可转换为 z,则表达式的类型是 z 的类型,同样,如果 z 可转换为 y,则类型是 y 的类型。

在您的情况下,y 的类型是 DBNull,y 的类型是 m_dtLastLogin 的类型(可能是日期时间)。这两种类型不能相互转换,也没有共同的基类型(Object 除外),所以编译器不知道该怎么做。

但是,您可以通过将 y 或 z 转换为对象来帮助编译器:

drow["LastLogin"] = (m_dtLastLogin == null) ? (object)System.DBNull.Value : m_dtLastLogin;

drow["LastLogin"] = (m_dtLastLogin == null) ? System.DBNull.Value : (object)m_dtLastLogin;

这样整个表达式就有了类型对象,然后可以将其分配给drow["LastLogin"]

参考: C# 语言规范 - http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-334.pdf

第 14.13 节,条件运算符

引用

?: 运算符的第二个和第三个操作数控制条件表达式的类型。设 X 和 Y 是第二个和第三个操作数的类型。那么,

  • 如果 X 和 Y 是同一类型,那么这是条件表达式的类型。

  • 否则,如果存在从 X 到 Y 的隐式转换(第 13.1 节),而不是从 Y 到 X,则 Y 是条件表达式的类型。

  • 否则,如果存在从 Y 到 X 的隐式转换(第 13.1 节),而不是从 X 到 Y,则 X 是条件表达式的类型。

  • 否则无法确定表达式类型,出现编译时错误。

【讨论】:

  • 有道理。我对 (DateTime?)System.DBNull.Value 的对象太具体了
  • 我添加了对语言规范的引用。
【解决方案2】:

将两者都转换为“对象”:

drow["LastLogin"] = (m_dtLastLogin == null) ? (object)System.DBNull.Value : 
    (object)m_dtLastLogin;

条件运算符要求两个部分(“then”和“else”部分)计算为相同的类型,这将是表达式的结果类型。

您的原始版本没有强制转换,因为它最终出现在 object 类型的字段中。

【讨论】:

  • 这两个部分不需要具有相同的类型。它们只需要可转换为一种常见类型。
猜你喜欢
  • 2011-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-26
  • 2015-11-09
  • 1970-01-01
  • 2021-09-22
  • 1970-01-01
相关资源
最近更新 更多