三元条件中的隐式转换问题[重复]

2023-12-01

可能的重复:
条件运算符不能隐式转换?
为什么 null 需要在这里进行显式类型转换?

我进行了搜索,但没有找到关于为什么会发生以下情况的良好解释。
我有两个具有共同接口的类,并且我尝试使用三元运算符初始化此接口类型的实例,如下所示,但这无法编译并显示错误“无法确定条件表达式的类型,因为之间没有隐式转换” “xxx.Class1”和“xxx.Class2”:

public ConsoleLogger : ILogger  { .... }

public SuppressLogger : ILogger  { .... }

static void Main(string[] args)
{
   .....
   // The following creates the compile error
   ILogger logger = suppressLogging ? new SuppressLogger() : new ConsoleLogger();
}

如果我将第一个条件显式转换为我的界面,则此方法有效:

   ILogger logger = suppressLogging ? ((ILogger)new SuppressLogger()) : new ConsoleLogger();

显然我总是可以这样做:

   ILogger logger;
   if (suppressLogging)
   {
       logger = new SuppressLogger();
   }
   else
   {
       logger = new ConsoleLogger();
   }

替代方案很好,但我不太明白为什么第一个选项因隐式转换错误而失败,因为在我看来,这两个类都是 ILogger 类型,并且我并不真正希望进行转换(隐式或显式) )。我确信这可能是静态语言编译问题,但我想了解发生了什么。


这是 C# 的两个特性融合的结果。

首先,C# 永远不会为您“魔法”出一种类型。如果 C# 必须从给定的一组类型中确定“最佳”类型,它总是选择您提供的类型之一。它从来不会说“你给我的类型都不是最好的类型;因为你给我的选择都很糟糕,所以我会随机选择一些你没有给我选择的东西。”

第二个是 C# 的原因是inside to outside。我们不会说“哦,我看到您正在尝试将条件运算符结果分配给 ILogger;让我确保两个分支都能工作。”相反的情况会发生:C# 说“让我确定两个分支返回的最佳类型,并验证最佳类型是否可转换为目标类型。”

第二条规则是明智的,因为目标类型可能是我们想要确定的。当你说D d = b ? c : a;目标类型是什么一目了然。但假设你正在打电话M(b?c:a)? M 可能有一百种不同的重载,每种重载都有不同的形式参数类型!我们必须确定参数的类型是什么,然后丢弃由于参数类型与形参类型不兼容而不适用的 M 重载;我们不会走相反的路。

考虑一下如果我们走另一条路会发生什么:

M1( b1 ? M2( b3 ? M4( ) : M5 ( ) ) : M6 ( b7 ? M8() : M9() ) );

假设 M1、M2 和 M6 各有一百个重载。你做什么工作?你说,好吧,如果这是 M1(Foo) 那么 M2(...) 和 M6(...) 必须都可以转换为 Foo。他们是吗?让我们来看看吧。 M2的过载是多少?有一百种可能性。让我们看看它们中的每一个是否都可以从 M4 和 M5 的返回类型进行转换...好吧,我们已经尝试了所有这些,所以我们找到了一个可以工作的 M2。那么M6呢?如果我们找到的“最好的”M2 与“最好的”M6 不兼容怎么办?我们是否应该回溯并继续重新尝试所有 100 x 100 种可能性,直到找到兼容的一对?问题变得越来越严重。

We do以这种方式对 lambda 进行推理,因此涉及 lambda 的重载决策在 C# 中至少是 NP-HARD。那里的情况很糟糕;我们宁愿不添加更多的 NP-HARD 问题供编译器解决。

您也可以在语言的其他地方看到第一条规则的作用。例如,如果你说:ILogger[] loggers = new[] { consoleLogger, suppressLogger };你会得到类似的错误;推断的数组元素类型必须是最佳类型给出的键入表达式。如果无法从中确定最佳类型,我们不会尝试寻找您未提供的类型。

类型推断也是如此。如果你说:

void M<T>(T t1, T t2) { ... }
...
M(consoleLogger, suppressLogger);

那么T就不会被推断为ILogger;这将是一个错误。 T 被推断为提供的参数类型中的最佳类型,并且其中没有最佳类型。

有关此设计决策如何影响条件运算符行为的更多详细信息,请参阅我关于该主题的系列文章.

如果您对为什么“从外到内”工作的重载解析是 NP-HARD 感兴趣,请参阅本文.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

三元条件中的隐式转换问题[重复] 的相关文章

  • BASIC 中的 C 语言中的 PeekInt、PokeInt、Peek、Poke 等效项

    我想知道该命令的等效项是什么Peek and Poke 基本和其他变体 用 C 语言 类似PeekInt PokeInt 整数 涉及内存条的东西 我知道在 C 语言中有很多方法可以做到这一点 我正在尝试将基本程序移植到 C 语言 这只是使用
  • STL 迭代器:前缀增量更快? [复制]

    这个问题在这里已经有答案了 可能的重复 C 中的预增量比后增量快 正确吗 如果是 为什么呢 https stackoverflow com questions 2020184 preincrement faster than postinc
  • 在一个数据访问层中处理多个连接字符串

    我有一个有趣的困境 我目前有一个数据访问层 它必须与多个域一起使用 并且每个域都有多个数据库存储库 具体取决于所调用的存储过程 目前 我只需使用 SWITCH 语句来确定应用程序正在运行的计算机 并从 Web config 返回适当的连接字
  • 类型中的属性名称必须是唯一的

    我正在使用 Entity Framework 5 并且有以下实体 public class User public Int32 Id get set public String Username get set public virtual
  • 如何在 Cassandra 中存储无符号整数?

    我通过 Datastax 驱动程序在 Cassandra 中存储一些数据 并且需要存储无符号 16 位和 32 位整数 对于无符号 16 位整数 我可以轻松地将它们存储为有符号 32 位整数 并根据需要进行转换 然而 对于无符号 64 位整
  • std::vector 与 std::stack

    有什么区别std vector and std stack 显然 向量可以删除集合中的项目 尽管比列表慢得多 而堆栈被构建为仅后进先出的集合 然而 堆栈对于最终物品操作是否更快 它是链表还是动态重新分配的数组 我找不到关于堆栈的太多信息 但
  • free 和 malloc 在 C 中如何工作?

    我试图弄清楚如果我尝试 从中间 释放指针会发生什么 例如 看下面的代码 char ptr char malloc 10 sizeof char for char i 0 i lt 10 i ptr i i 10 ptr ptr ptr pt
  • -webkit-box-shadow 与 QtWebKit 模糊?

    当时有什么方法可以实现 webkit box shadow 的工作模糊吗 看完这篇评论错误报告 https bugs webkit org show bug cgi id 23291 我认识到这仍然是一个问题 尽管错误报告被标记为RESOL
  • 两个静态变量同名(两个不同的文件),并在任何其他文件中 extern 其中一个

    在一个文件中将变量声明为 static 并在另一个文件中进行 extern 声明 我认为这会在链接时出现错误 因为 extern 变量不会在任何对象中看到 因为在其他文件中声明的变量带有限定符 static 但不知何故 链接器 瑞萨 没有显
  • C# - 当代表执行异步任务时,我仍然需要 System.Threading 吗?

    由于我可以使用委托执行异步操作 我怀疑在我的应用程序中使用 System Threading 的机会很小 是否存在我无法避免 System Threading 的基本情况 只是我正处于学习阶段 例子 class Program public
  • 两个类可以使用 C++ 互相查看吗?

    所以我有一个 A 类 我想在其中调用一些 B 类函数 所以我包括 b h 但是 在 B 类中 我想调用 A 类函数 如果我包含 a h 它最终会陷入无限循环 对吗 我能做什么呢 仅将成员函数声明放在头文件 h 中 并将成员函数定义放在实现文
  • 实例化类时重写虚拟方法

    我有一个带有一些虚函数的类 让我们假设这是其中之一 public class AClassWhatever protected virtual string DoAThingToAString string inputString retu
  • 空指针与 int 等价

    Bjarne 在 C 编程语言 中写道 空指针与整数零不同 但 0 可以用作空指针的指针初始值设定项 这是否意味着 void voidPointer 0 int zero 0 int castPointer reinterpret cast
  • 如何实例化 ODataQueryOptions

    我有一个工作 简化 ODataController用下面的方法 public class MyTypeController ODataController HttpGet EnableQuery ODataRoute myTypes pub
  • 为什么 isnormal() 说一个值是正常的,而实际上不是?

    include
  • 在 WPF 中使用 ReactiveUI 提供长时间运行命令反馈的正确方法

    我有一个 C WPF NET 4 5 应用程序 用户将用它来打开某些文件 然后 应用程序将经历很多动作 读取文件 通过许多插件和解析器传递它 这些文件可能相当大 gt 100MB 因此这可能需要一段时间 我想让用户了解 UI 中发生的情况
  • C# 中的 IPC 机制 - 用法和最佳实践

    不久前我在 Win32 代码中使用了 IPC 临界区 事件和信号量 NET环境下场景如何 是否有任何教程解释所有可用选项以及何时使用以及为什么 微软最近在IPC方面的东西是Windows 通信基础 http en wikipedia org
  • C++ 继承的内存布局

    如果我有两个类 一个类继承另一个类 并且子类仅包含函数 那么这两个类的内存布局是否相同 e g class Base int a b c class Derived public Base only functions 我读过编译器无法对数
  • C++ 中的 include 和 using 命名空间

    用于使用cout 我需要指定两者 include
  • 在OpenGL中,我可以在坐标(5, 5)处精确地绘制一个像素吗?

    我所说的 5 5 正是指第五行第五列 我发现使用屏幕坐标来绘制东西非常困难 OpenGL 中的所有坐标都是相对的 通常范围从 1 0 到 1 0 为什么阻止程序员使用屏幕坐标 窗口坐标如此严重 最简单的方法可能是通过以下方式设置投影以匹配渲

随机推荐

  • 访问 Service 中的请求范围 Bean

    我有一颗普通豆 它是 a Scope request 或 b 放置在HttpServletRequest通过过滤器 拦截器 如何在 a 中访问这个 bean Service哪一种是应用程序范围的单例 这样做的原因是 因为我有一个自定义对象R
  • 使用 Heroku 设置 Paperclip Amazon S3

    has attached file image storage gt s3 s3 credentials gt RAILS ROOT config s3 yml path gt style filename 我不知道什么 path gt s
  • 缺少 1 个必需的位置参数:'self'

    这是我的代码 class Email Stuff def init self self emailaddr None self recipaddr None self EmailUser None self EmailPass None d
  • 如何确定文本节点中被点击的字符?

    我可以设置一个事件侦听器来告诉我 HTML 文档中某个位置何时发生鼠标单击 但是 如果单击发生在某些文本上 我需要知道单击发生在文本中的哪个字符上 有没有办法做到这一点 我能想到一些非常令人讨厌的解决方案 例如 对于文档中的每个字符 我可以
  • HttpClient上传大文件并显示发送的字节数

    我找到了这个代码示例 import org apache http params CoreProtocolPNames import org apache http util EntityUtils public class PostFil
  • 从 Excel 将超过 65.535 行导入到 MS Access

    我正在运行以下代码将整个工作表从 Excel 导入到 Access 该工作表有 77k 行 但 Access 仅导入 65 535 行 关于如何修复它有任何疑问吗 Excel 和 Access 都是 2013 版本 Function imp
  • 为什么我们需要将 MDSYS.ST_GEOMETRY 视为 ST_LINESTRING 才能使用 ST_PointN(1)?

    MDSYS ST GEOMETRY 甲骨文18c 以下查询有效 它从 MDSYS ST GEOMETRY 中提取第一个点 Source https www spdba com au using oracles st geometry typ
  • 使用intel内联汇编器编码带有进位的bigint add

    我想做一个快速代码来添加大整数中的 64 位数字 uint64 t ans n uint64 t a n b n assume initialized values for int i 0 i lt n i ans i a i b i 但以
  • 在 webgl 片段着色器中按颜色计算像素

    我有 2d 纹理 S 并且想要返回 3d 纹理 H 这样像素 H r g b 等于纹理 S 中颜色 rgb 的像素数 基本上是纹理 S 中颜色的直方图 我知道遮挡查询 但它仅在 webgl2 中可用 而 IIUC 即使在那里也只能使用布尔结
  • Android SeekBar 拇指自定义

    我想隐藏栏 只想显示拇指 我用 max height 0dip 做到了 但它没有完全起作用 我还想在拇指上设置文本并使用多个图像创建拇指 例如 拇指按钮像图像一样并且具有文本 并且该按钮具有尾部下字 它随着行增量而增加 关于删除背景 我设法
  • 从 python 脚本获取 shell 脚本“读取”值

    外壳脚本 你好 sh bin bash echo Enter your name read name echo Hello name 我想从 python 中调用 Hello sh 并以非交互方式填充变量 name 如何做呢 不知道如何阅读
  • 在 Swift 中的 UITableViewController 之上添加一个 UIView

    我目前使用 UITableViewController PFQueryTableViewController 我想在 TableView 顶部显示一个 UIView 理想情况下 我想在故事板中执行此操作 这样我就可以轻松地向其中添加其他标签
  • nltk下载url授权问题

    我尝试使用 nltk download 更新我的 nltk 数据 但收到 HTTP 错误 401 需要授权 当我追踪有问题的网址时 我在 downloader py 中找到了它 DEFAULT URL http nltk googlecod
  • 如何使用 GPS 在 Android 中获取我的当前位置?

    我想通过 GPS 以地址形式获取我当前的位置 我正在使用android studio 它说我的应用程序停止工作 其中有什么错误呢 有人可以帮我摆脱这个困境吗 我在 Activity main xml 文件中的代码是
  • 充气城堡:PEMReader => PEMParser

    拥有 PEM 证书 例如 BEGIN RSA PRIVATE KEY Proc Type 4 ENCRYPTED DEK Info AES 256 CBC B9846B5D1803E 使用 BC 1 46 我使用以下代码提取密钥对 int
  • 电子表格上的 Google 日期与脚本记录器中的日期不同。这是时区问题吗?

    我已在 Google 电子表格上输入了应发送电子邮件的具体日期 我有一个脚本 它从电子表格中获取值 以 1 比较 应发送的日期电子邮件 是否等于今天 如果是 则运行脚本或 2 将今天的日期输入到电子表格中 即 日期 电子邮件已发送 我看到记
  • Java Jar hell 运行时异常

    我在运行单元测试时遇到了 jar hell 的问题 java lang RuntimeException found jar hell in test classpath at org elasticsearch bootstrap Boo
  • HTML 5 本地存储

    我正在寻找一种将几乎所有 JS 和 CSS 存储在本地存储中的方法 我知道如何使用 CSS 来做到这一点 似乎工作顺利 但是 如果您尝试存储具有任何 HTML 调用的 JS 则会停止保存到本地存储 理想情况下 我只想创建一个源文件列表以供浏
  • 如何在 Angular 2 中包含 JQuery 插件?

    我在 Angular 2 项目中安装了 jquery 插件Link npm i jquery bootstrap scrolling tabs 并添加 angular cli json styles styles css node modu
  • 三元条件中的隐式转换问题[重复]

    这个问题在这里已经有答案了 可能的重复 条件运算符不能隐式转换 为什么 null 需要在这里进行显式类型转换 我进行了搜索 但没有找到关于为什么会发生以下情况的良好解释 我有两个具有共同接口的类 并且我尝试使用三元运算符初始化此接口类型的实