【问题标题】:C# Ternary expression type conversionC# 三元表达式类型转换
【发布时间】:2023-03-19 07:34:01
【问题描述】:

为什么编译器不能正确地自动转换这个表达式中的值?

var input = "Hello";
object x = string.IsNullOrEmpty(input) ? input : DBNull.Value;

//could try this too and get similar compile time error
object x2 = string.IsNullOrEmpty(input) ? 1 : input;

我了解 DBNull.Value 不能转换为字符串;但是,我很好奇为什么它不能合并成一个对象,因为结果只是存储一个引用。如果将(object) 放在 DBNull.Value 前面,它将编译并运行得很好。

【问题讨论】:

  • 除 gdoron 之外的所有答案都没有抓住重点。这不是一个“嘿,帮我编译一下”的问题。更多的是询问为什么 c# 编译器不能或选择不能查看分配给的变量的类型与第二个和第三个参数中的变量类型。
  • 找到了一个稍微不相关的问题的答案stackoverflow.com/a/2215959/186359 我认为它基本上证明了在评估表达式时不能添加信息(赋值变量的类型)。我认为这可能是真正的答案

标签: c# ternary-operator compile-time


【解决方案1】:

这是因为string 不能转换为DbNull,反之亦然。使用三元运算符时,两个结果操作数必须兼容。

【讨论】:

  • 我会用 “需要从一种类型到另一种类型的隐式转换。”
  • @gdoron 也没有显式转换。
  • 我已经拿到那部分了。我想知道为什么编译器不可能(可行)查看分配给(对象)的类型并意识到这两种类型都隐式转换为对象。忘记他们彼此之间的关系。
  • @MattPhillips:这根本不是语言的工作方式。尽管这里看起来很简单,但请考虑调用重载方法的其他情况,其中可能存在各种可能的转换。如果每个表达式都有自己的类型,并且完全独立于它的使用方式来标识,那就简单多了。有一些例外,例如 lambda 表达式和 null 文字,但它们增加了语言规则的复杂性 - 因此这些情况被保持在最低限度。
【解决方案2】:

修复它:

string x = string.IsNullOrEmpty(input) ?
                                       input :
                                       DBNull.Value.ToString();

我在 Eric Lippert blog 中找到了这个极好的解释:

?: 运算符的规范声明如下:

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

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

  • 否则,如果存在从 X 到 Y 的隐式转换, 但不是从 Y 到 X,则 Y 是条件表达式的类型。

  • 否则,如果存在从 Y 到 X 的隐式转换,而不是从 X 到 Y,那么 X 就是条件表达式的类型。

  • 否则, 无法确定表达式类型,并发生编译时错误。

在这种情况下:

  • stringDBNull 不是同一类型。
  • string 没有隐式转换为 DBNull
  • DBNull 没有到 string 的隐式转换

所以我们最终会遇到编译时错误。

编译器不会检查可以“持有”这两种类型的类型。

【讨论】:

  • 这是有道理的。我想我要找的是implicit 部分。 Kinda 让您想知道为什么它不尝试隐式转换为它们分配的变量的类型。如果我要存储到对象,我不在乎实际类型是什么,因为无论如何我只是存储对它的引用。
  • @MattPhillips。然后你找到了... :)
【解决方案3】:

帮助编译器找到你想要的通用基类型,像这样:

object x = string.IsNullOrEmpty(input) ? (object)input : DBNull.Value;

【讨论】:

    猜你喜欢
    • 2015-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-16
    • 2016-03-08
    • 2015-06-07
    相关资源
    最近更新 更多