关于 C# 语言规范中隐式转换的问题

2024-01-06

第 6.1 节 隐式转换定义一个身份转换 thusly:

身份转换从任何类型转换为相同类型。这种转换的存在使得已经具有所需类型的实体可以说可以转换为该类型。

现在,这些句子的目的是什么?

(在第 6.1.6 节隐式引用转换中)

隐式引用转换为:

  • [...]
  • From any reference-type to a reference-type T if it has an implicit identity or reference conversion to a reference-type T0 and T0 has an identity conversion to T.

and:

(在§6.1.7 拳击转换中)

  • A value type has a boxing conversion to an interface type I if it has a boxing conversion to an interface type I0 and I0 has an identity conversion to I.

最初它们看起来是多余的(同义反复)。但他们的存在一定是有目的的,那么他们为什么会存在呢?

Can you give an example of two types T1, T2 such that T1 would not be implicitly convertible to T2 if it weren’t for the above-quoted paragraphs?


2010 年 9 月 22 日更新:

我怀疑除了 Timwi 之外还有人会读到这篇文章。即便如此,我还是想对这个答案进行一些编辑,因为新的答案现已被接受,并且关于规范引用的摘录是否正确的争论仍在继续(至少在我可能想象的世界中)在技​​术上是多余的。我没有添加太多内容,但内容太多,无法发表评论。大部分更新可以在标题下找到“转换涉及dynamic type" below.


2010 年 9 月 19 日更新:

在您的评论中:

[这没有道理。

该死的,蒂姆维,你这么说a lot。但好吧,那么;你让我处于守势,所以开始吧!

免责声明:我有当然不尽可能仔细地检查规范。根据您最近提出的一些问题,您似乎最近对此进行了相当多的研究。这自然会让你比 SO 上的大多数用户更熟悉很多细节;因此,就像您可能从埃里克·利珀特以外的任何人那里收到的大多数答案一样,这可能不会令您满意。

不同场所

首先,你的问题的前提是,如果突出显示的陈述是多余的,那么他们不服务purpose。我的回答的前提是,如果多余的陈述澄清了一些事情,那么它们并不一定是没有目的的。对每个人来说并不明显。这些都是矛盾的前提。如果我们不能在前提上达成一致,我们就无法进行简单的逻辑论证。我只是要求你重新考虑你的前提。

然而,你的回应是重申你的前提是:“如果这些句子确实是多余的,那么它们只会让读者感到困惑,而不会澄清任何事情。”

(顺便说一句,我喜欢你如何将自己设置为该规范的所有读者的代表。)

确切地说,我不能责怪你担任这个职位。我的意思是,确实如此seem明显的。而且我在原来的回答中没有给出任何具体的例子。所以下面我将尝试包括一些具体的例子。但首先,让我退后一步,提出我的看法,解释为什么会出现这种奇怪的现象身份转换概念首先存在于规范中。

目的身份转换定义

乍一看,这个定义似乎相当多余。这不是说任何类型 T 的实例都可以转换为……好吧,转换为 T 吗?是的。但我假设*该定义的目的是为规范提供适当的词汇来利用以下概念:类型标识在讨论的背景下转换.

This allows for statements about conversions which are essentially transitive in nature. The first point you quoted from the spec as an example of a tautological statement falls into this category. It says that if an implicit conversion is defined for some type (I'll call it K) to another type T0 and T0 has an identity conversion to T, then K is implicitly convertible to T. By the definition of identity conversion given above, "has an identity conversion to" really means "is the same type as." So the statement is redundant.

But again: the identity conversion definition exists in the first place to equip the spec with a formal language for describing conversions without having to say things like "if T0 and T are really the same type."

好的,是时候看具体例子了。

存在隐式转换的地方might不明显some开发商

Note: A 好多了Eric Lippert 在中提供了示例他对问题的回答 https://stackoverflow.com/questions/3736789/question-regarding-implicit-conversions-in-the-c-language-specification/3748757#3748757。我留下前两个例子只是对我的观点的次要强化。我还添加了第三个示例,具体化了之间存在的身份转换object and dynamic正如埃里克的回答所指出的。

传递引用转换

假设你有两种类型,M and N,并且您已经定义了如下隐式转换:

public static implicit operator M(N n);

然后你可以编写这样的代码:

N n = new N();
M m = n;

现在假设您有一个包含此内容的文件using顶部声明:

using K = M;

然后你可以在文件后面看到:

N n = new N();
K k = n;

好的,在我继续之前,我意识到这很明显you and me.但我的答案是,而且从一开始就是这样,它可能not显而易见everyone,因此指定它--同时多余的——还有一个purpose.

That purpose是:向那些摸不着头脑、查看该代码的人表明,它是合法的。一个隐式转换存在从 N 到 M,并且身份转换从 M 到 K 存在(即 M 和 K 是同一类型);所以存在从 N 到 K 的隐式转换。它不是just合乎逻辑(尽管可能be逻辑);它就在规范中。否则,人们可能会错误地认为像下面这样的东西是必要的:

K k = (M)n;

显然,事实并非如此。

传递拳击转换

或者采取类型int. An int可以装箱为IComparable<int>, 正确的?所以这是合法的:

int i = 10;
IComparable<int> x = i;

现在考虑一下:

int i = 10;
IComparable<System.Int32> x = i;

Again, yes,可能是obvious献给你、我以及 90% 可能遇到过它的开发者。但对于那些没有立即看到这一点的极少数人来说:拳击转换存在于int to IComparable<int>, 和身份转换存在于IComparable<int> to IComparable<System.Int32> (i.e., IComparable<int> and IComparable<System.Int32>是同一类型);所以拳击转换存在于int to IComparable<System.Int32>.

转换涉及dynamic type

我将借用上面的引用转换示例,并稍微调整它以说明之间的恒等关系object and dynamic在规范的 4.0 版本中。

假设我们有以下类型M<T> and N,并在某处定义了以下隐式转换:

public static implicit operator M<object>(N n);

那么以下是合法的:

N n = new N();
M<dynamic> m = n;

显然,上面的内容还少得多obvious比前两个例子。但这是一个价值百万美元的问题:上面的会still即使问题中引用的规范摘录不存在,也是合法的吗?(我将把这些摘录称为Q为简洁起见。)如果答案是肯定的,那么Q事实上是多余的。如果不是,那就不是。

我相信答案是肯定的。

考虑以下的定义身份转换,在第 6.1.1 节中定义(我在这里包含整个部分,因为它很短):

身份转换从任何类型转换为相同类型。这种转换的存在使得已经具有所需类型的实体可以说可以转换为该类型。

Because object and dynamic被认为是等价的,之间存在身份转换object and dynamic, 以及替换所有出现的相同构造类型之间dynamic with object. [强调我的]

(最后一部分也包含在第 4.7 节中,它定义了dynamic type.)

现在让我们再看一下代码。我特别对这一行感兴趣:

M<dynamic> m = n;

本声明的合法性(不考虑Q--记住,正在讨论的问题是上述声明的假设合法性if Q did not存在),因为M<T> and N是自定义类型,取决于用户定义的隐式转换之间是否存在N and M<dynamic>.

存在隐式转换N to M<object>。根据上面引用的规范部分,之间存在身份转换M<object> and M<dynamic>。根据定义身份转换, M<object> and M<dynamic> 是同一类型.

因此,就像前两个(更明显的)示例一样,我相信确实存在隐式转换N to M<dynamic> 即使不采取Q考虑到,正如确实存在隐式转换一样N to K在第一个示例中,并且存在装箱转换int to IComparable<System.Int32>在第二个例子中。

Without Q,这不太明显(因此Q的存在);但这并不意味着它是错误的 (i.e., Q is not 必要的来定义此行为)。它只是让它变得不那么明显。

结论

我在最初的回答中说过,这是“显而易见的”解释,因为在我看来,你找错了树。您最初提出了这个挑战:

Can you give an example of two types T1, T2 such that T1 would not be implicitly convertible to T2 if it weren’t for the above-quoted paragraphs?

No one's going to meet this challenge, Timwi, because it's impossible. Take the first excerpt about reference conversions. It is saying that a type K is implicitly convertible to a type T if it is implicitly convertible to T0 and T0 is the same as T. Deconstruct this, put it back together, and you're left with an obvious tautology: K is implicitly convertible to T if it's implicitly convertible to T. Does this introduce any new implicit conversions? Of course not.

所以也许本·沃伊特的评论是正确的;也许您所询问的这些要点最好放在脚注中,而不是放在正文中。无论如何,我很清楚他们are多余的,所以从前提开始他们不能是多余的,否则他们就不会在那里就是去做一件愚蠢的事。愿意接受这样一个事实:冗余的陈述可能仍然可以阐明一个对每个人来说可能并不明显的概念,并且更容易接受这些陈述的本来面目。

多余的?是的。同义反复?是的。无意义?在my意见,没有。

*Obviously, I did not have any part in writing the C# language specification. If I did, this answer would be a lot more authoritative. As it is, it simply represents one guy's feeble attempt to make sense of a rather complex document.


原答案

我认为您(也许是故意的)忽略了这里最明显的答案。

考虑你的问题中的这两句话:

(1)最初它们看起来是多余的 (同义反复)。(2)但他们必须在那里 是有目的的,那么他们为什么在那里呢?

对我来说,这两句话放在一起的含义是同义反复的陈述没有任何意义。但仅仅因为一个陈述是从既定前提逻辑上得出的,并不会让每个人都明白这一点。换句话说,即使(1)是真的,答案是(2)可能只是:使阅读规范的任何人都清楚所描述的行为.

现在你可能会争辩说,即使有些东西不是obvious,如果它提供了冗余定义,它仍然不属于规范。对于这种潜在的反对意见,我只能说:现实一点。 (在我看来)梳理一份文件并剔除所有陈述是不太实际的,这些陈述只是陈述可以从先前陈述中推断出的事实。

If this were作为一种常见的做法,我想你会发现很多文献——不仅仅是规格,还有研究论文、文章、教科书等——会更短、更密集,也更难理解。

所以:是的,也许它们是多余的。但这并不能否定他们的目的。

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

关于 C# 语言规范中隐式转换的问题 的相关文章

  • 是否有可能劫持标准输出

    我正在尝试使用 C 重定向 Windows XP 上已运行进程的标准输出 我知道如果我自己生成进程 我可以做到这一点 但对于这个应用程序 我更喜欢一个 监听器 我可以附加到另一个进程 这在纯 Net 中可能吗 如果不可能 在 Win32 中
  • 为什么我会收到未找到分析器的警告?

    我创建了一个玩具项目来检查最新的 NET 7 预览版 5 和正则表达式代码生成 它效果很好 所以我对现有项目应用了相同的更改 不是为了生产 而是为了个人生产力 由于某种原因 我收到这些警告 CS8032 An instance of ana
  • 最新 .Net MongoDb.Driver 的连接问题

    我创建了一个 MongoLab 沙箱数据库 我与 MongoChef 连接 效果很好 我通过 Nuget 安装了 MongoDB Driver 2 2 2 我编写了一些简单的 C 演示代码 但就是无法使其工作 连接字符串是直接从 Mongo
  • 使用 C# 将多个音频样本混合到单个文件中

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找一个能够创建音频文件 mp3 或 wav 的库 NAudio http www codeple
  • Dapper 在执行时挂起

    我有一个 IDb连接 sql UPDATE 表名 SET json json lastupdate SYSDATE WHERE id id var param new DynamicParameters param Add json jso
  • 将 dataGridView 中选定的行作为对象检索

    我有一堂这样的课 public partial class AdressBokPerson public long Session get set public string F rnamn get set public string Ef
  • .NET 5 EF Core SaveChangesAsync 因错误而挂起

    尽管这个问题有很多结果 但没有一个真正给我明确的答案 每次我尝试通过 AddAsync 和 SaveChangesAsync 方法插入错误数据 例如重复的主键 时 我都会看到以下日志 执行 DbCommand 失败 15 毫秒 我还在 SQ
  • 在c#中获取没有时间的日期

    我的表上有一列 缺勤日期时间 日期 当我想要获取包含日期的行时 它返回 0 行 这是我的 C 代码 DateTime ClassDate DateTime Parse lblDate Content ToString var Abs dbs
  • 处理“未找到细胞”。 Excel 中的错误

    我正在使用 Excel VSTO 应用程序并使用以下代码在工作表中查找错误单元格 Excel Range rngTemp Excel Range rngErrorRange Excel Worksheet Sheet1 Excel Work
  • 我可以将 UseCSharpNullComparisonBehavior 用于单个查询吗?

    我有一个查询 该查询曾经是存储过程 现已转换为 EF 查询 现在已经超时了 使用 SQL Profiler 我可以看到生成的 SQL 的唯一区别是 EF 转变的新行为entity Property value into entity Pro
  • 如何构建一棵与或树?

    我需要一个支持 与 和 或 的树结构 例如 给定一个正则表达式 如ab c d e 我想把它变成一棵树 所以 一开始我们有两个 或 分支 它可以向下ab or c d e 如果你低头ab分支 你得到两个节点 a and b or a其次是b
  • 如何在 C# 中更改公共 IP 地址

    我正在创建一个 C winform 应用程序 我想在其中更改公共 IP 地址 而不是像 Hotspot Shield ZenMate OpenVPN 等那样更改 IPv4 地址 我已经检查了以下链接 但没有找到足够的帮助 所以我发布了这个问
  • 传递数组时在 C 中的函数参数中强制指定数组大小

    Context 在 C 中 我有一个以数组作为参数的函数 该参数用作该函数的输出 输出的大小始终相同 我会 让阅读代码的人清楚所需的大小 不过它已经在函数注释中了 理想情况下 编译会输出警告或错误 这样我就可以在编译时而不是运行时防止出现问
  • 如何同步nosql db(ravendb)中的更改

    我已经开始在 RavenDB 的示例上学习 NoSQL 我从一个最简单的模型开始 假设我们有由用户创建的主题 public class Topic public string Id get protected set public stri
  • 如何从 Access 数据库中读取“是/否”值作为布尔值?

    帮我找回YES NO来自 MS Access 的布尔格式数据类型 我尝试解析它 但它总是返回 false 更新 实际上不是问题抱歉 它确实接受 YES NO 作为布尔值 OleDbconnection dbConnect new OleDb
  • Xcode 7 调试器不会中断内联标头函数

    过去五年我一直在各种 C 项目中使用 Xcode 没有出现这个问题 今天 我打开了一个较旧的项目 大约 2 年前 并尝试通过在该函数中放置一个活动断点来调试头文件中的内联函数 由于某种原因 调试器不会中断此代码 但是 如果我在调用该函数的
  • 当我的进程被终止时到底会发生什么?

    我有一个包含本机代码和托管代码的混合进程 在 Windows Server 2003 上运行 当我从进程资源管理器中终止进程时 它会进入 100 cpu 的状态 并在消失之前保持这种状态一段时间 有时甚至 10 分钟 在此期间我无法 杀死
  • 如何在c#中创建多线程

    我需要监听机器中的所有串行端口 假设我的机器有 4 个串行端口 我必须创建 4 个线程并开始分别使用附加线程监听每个端口 我使用此代码来获取我的机器中的端口数量 private SerialPort comPort new SerialPo
  • 如何在 C 中创建最低有效位设置为 1 的掩码

    这个功能如何运作 最低有效 n 位设置为 1 的掩码 Example n 6 gt 0x2F n 17 gt 0x1FFFF 我根本不明白这些 尤其是 n 6 gt 0x2F 另外 什么是面膜 通常的方法是采取1 并将其左移n位 这会给你类
  • 在windows + opengl中选择图形设备

    我知道如何使用 openGL 打开窗口 使用 Win32 或其他工具包 但是当系统有2块显卡时 如何选择要渲染的图形设备 我的编程语言是 C 我专注于 Windows 但任何示例都将受到欢迎 编辑 也许更好地解释我的问题是个好主意 以便添加

随机推荐

  • 使用 React Suspense 和 React.lazy 子组件进行 Jest/Enzyme 类组件测试

    因此 我将类组件中使用的导入转换为 React lazy import api 并将其包装在 Suspense 标记中 当我测试该类组件时 酶抛出错误 Enzyme Internal Error unknown node with tag
  • 具有动态数据的 SwiftUI 分层选取器

    我正在尝试在 SwiftUI XCode 11 3 1 中使用带有动态数据的多个选择器 该应用程序有时会崩溃 有时会冻结或在模拟器和运行 iOS 13 3 1 的真实设备上的选择器中显示错误的数据 我尝试了答案中的建议这个问题 https
  • Flutter ListView 双向延迟加载(向上、向下)

    我希望在 flutter 中有一个 ListView 它提供两个方向 向上 向下 的延迟加载 例子 后台数据库理论上可以显示60000条信息 首先我想显示项目 100 120 从这些索引中 我希望能够在延迟加载新项目时上下滚动 需要考虑的事
  • 模板类中模板方法的声明模板定义之外

    有谁知道模板类中声明外模板方法的语法 例如 template
  • 在 asp.net MVC 中对表进行排序

    我想知道人们如何在 ASP NET MVC 中对表进行排序 我听说过 javascript 解决方案可以很好地处理非分页表 例如 jquery 的表排序器 但我需要一个可以处理分页表的解决方案 我正在做的项目目前使用以下解决方案 但我发现它
  • Haskell 将 Float 转换为 Int

    我还是个新手 试图创建一个在函数中使用的列表 并希望使其尽可能小 恰好是 logBase x y 但我无法将 logBase 转换为我可以在此列表中使用的内容 1 logBase x y 有什么建议么 您没有发布您收到的类型错误 但我想它是
  • int24 - 24 位整数数据类型

    C 中有 24 位原始整型数据类型吗 如果没有 是否可以创建一个类 int24 uint24 其目的可能是 处理 24 位格式的声音文件 在没有 alpha 通道的情况下操作位图数据 根据要求 我将使用位字段 struct int24 un
  • 使用 Linux 帧缓冲区进行图形处理,但禁用控制台文本

    我有一些 C 代码 可以在 Linux 帧缓冲区控制台上绘制简单的图形 我还使用树莓派及其复合视频输出 操作系统是 raspbian 我正在做一个不使用 X 的低级解决方案 我的图形运行良好 而且我还能够读取 USB 键盘并对按键做出响应
  • artifact:install 推送 super-pom 而不是我定义的 POM

    我在 Ant 文件中定义了一个 POM 构建工作正常 从存储库中提取正确的工件 但是 工件 安装任务推送到 super pom 而不是我指定的 pom 我使用以下 POM 文件
  • Olive (Mono) 如何实现 (W)PF?

    在阅读一本维基百科上有关 Mono 的文章 http en wikipedia org wiki Mono 28software 29 我发现有一个 Mono 子 副项目叫做Olive http mono wikia com wiki Ol
  • 使用正则表达式解析多行日志条目

    我正在尝试使用以下正则表达式解析 C 应用程序中的日志条目 0 9 4 0 9 2 2 3 1 对于格式如下的日志 日期 某种格式 level 应用程序名称 信息 哪里 我认为 匹配行的开头 启用 gm在正则表达式101上 0 9 4 0
  • 提交 JTA 事务后可以回滚它吗?

    我有一个提交的 JTA 事务 提交后可以回滚吗 如果是 怎么办 我有以下情况 我有一个更新了 3 个 DB 的后端层 我已经使用了 JTA 用户交易 如果任何数据库中的更新失败 则使用 utx rollback 回滚对 3 个数据库的所有更
  • 如果用纯 C++ 表示静态?

    简而言之问题 怎样才能实现static if在 c 11 中提出的功能 用普通的 c 历史和原始问题 最近我遇到了这样一个问题 我需要上课Sender具有类似的界面 class Sender void sendMessage void se
  • 证明强可能素数的素性

    使用米勒 拉宾测试的概率版本 我生成了中大 200 300 位 可能素数的列表 但可能还不够好 我需要know这些数字是素数 是否有一个库 最好是用 Python 包装或可包装 可以实现更有效的素性证明算法之一 或者 有谁知道我在哪里可以找
  • 如何从 PDO 失败“错误!:SQLSTATE[HY093]:无效的参数号:参数未定义”中获取更多信息?

    每隔一段时间 我就会在 PDO 中遇到如下错误 错误 SQLSTATE HY093 参数号无效 参数未定义 有没有办法获得更具体的错误 例如行号 文件名 缺少的参数等 而不是模糊的消息 首先 确保 PDO 设置为在错误时抛出异常 pdo g
  • 如何从另一个平面/简单配置单元表加载带有map[structs]的配置单元表

    我在 hive 中有 2 个表 其中有 Order 和 Order Detail 具有 1 n 关系并在 order id 上连接 我试图利用 hive 复杂数据类型 map struct 将其加载到单个表中 假设 ORDER 有以下数据
  • Eclipse CDT 新项目模板 - 如何添加库

    在 Eclipse CDT Indigo 中 有一个新功能允许您将新的 C C 模板项目添加到新项目向导中 我已经弄清楚如何在一定程度上成功地做到这一点 我可以创建一个仅依赖于简单源文件的基本项目 但现在我想创建一个 CPPUnit 项目
  • Python、Chrome 任务管理器 - 以编程方式访问 Chrome 任务管理器的文本而不使用 CHROMIUM

    因此 由于许多人都遇到过 Chrome 的内存使用量可能会让人衰弱的情况 所以我想以编程方式访问 Chrome 的任务管理器 或类似的东西 显示选项卡 它们的 PID 和子帧 如果可能 这样我就可以创建一个脚本来杀死它们 经过大量阅读 很多
  • PetaPoco 在带有触发器的表上插入失败

    我们使用 PetaPoco 作为 SQL 2008 数据库的数据访问工具 当尝试在附加了触发器的表上插入 更新行时 我们遇到了问题 我们正在使用 PetaPoco 的 db Save object 显示的错误是 如果 DML 语句包含 OU
  • 关于 C# 语言规范中隐式转换的问题

    第 6 1 节 隐式转换定义一个身份转换 thusly 身份转换从任何类型转换为相同类型 这种转换的存在使得已经具有所需类型的实体可以说可以转换为该类型 现在 这些句子的目的是什么 在第 6 1 6 节隐式引用转换中 隐式引用转换为 Fro