铸造和转换有什么区别?

Joe*_*sky 67 c# casting type-conversion

Eric Lippert对这个问题的评论让我彻底糊涂了.C#中的转换和转换有什么区别?

chr*_*ssr 80

转换是一种告诉编译器的方法"对象X实际上是Y型,继续进行处理."

转换是说"我知道对象X不是Y型,但是存在一种从Y型X创建新对象的方法,继续执行它."

  • 我喜欢这些简单的逻辑解释.+1 (11认同)
  • 我不相信这反映了埃里克试图说的精神.从我的阅读中,他并没有将行为描述为"要么是'cast`,要么是`convert`,而是将*cast*描述为代码中存在的内容(换句话说,*cast运算符*),其中***正是实际发生的事情.很少有转换导致相同的内存中表示(例如在同一类型的有符号和无符号版本之间进行转换,如`int`和`uint`,或转换为基类型和接口). (7认同)
  • 很好的定义,但为什么那么(int)5.5在C/C++中被称为强制转换?这绝对是一种转换. (6认同)
  • 我猜这个术语"演员"有一个混乱的定义和用法.转换原语涉及显式转换.它只是引用表现为chrissr解释的引用类型.这样做:`double a = 4.5; int b = a;`产生一个准确的错误信息暗指:`不能隐式地将类型'double'转换为'int'.存在显式转换(你是否错过了演员表?)`-----这些都在C#中,我怀疑C和C++是同一个故事. (2认同)
  • 我会说你所绘制的区别不是转换与转换,而是保持转换与表示改变转换的表示.在JScript团队中,我们通过调用前"转换"和后者"强制"来区分,但区别非常微妙. (2认同)

Jus*_*ner 45

我相信Eric想要说的是:

转换是一个描述语法的术语(因此是句法含义).

转换是一个术语,描述幕后实际采取的行动(以及语义含义).

cast-expression用于将表达式显式转换为给定类型.

形式为(T)E的强制转换表达式,其中T是一个类型而E是一元表达式,它执行E的值到类型T的显式转换(第13.2节).

似乎通过说语法中的强制转换操作符执行显式转换来支持它.

  • @Guffa:那么你所说的是"身份转换" - 从int到int的转换 - 不是转换?一个有趣的位置,但C#规范不支持. (6认同)
  • 不,我认为这不是他的意思.语法称为强制转换,但它并不总是在后台进行转换.如果您实际进行了投射,则无法进行转换.它甚至可能根本不创建任何代码,但只告诉编译器它应该考虑引用的类型. (5认同)
  • +1.到目前为止,我见过的唯一答案似乎与Eric所说的相符. (3认同)
  • 在C#语言的上下文中,强制转换意味着这一点.在IL的上下文中,`castclass`操作码具有其他人描述的含义(将引用解释为不同的类型.)因此'强制转换操作符'可以解析为发出的IL中的强制转换或转换. (2认同)
  • 有些转换只是重新解释,有些则不是,并且需要幕后的实际代码来执行。有些转换是隐式完成的,其他转换则需要显式转换。上述两个陈述之间*没有*相关性;某些隐式转换会导致生成代码,而某些显式转换则不会。但是,(我相信)生成的转换可能引发异常的所有情况都需要显式强制转换。 (2认同)

Eri*_*ert 42

我想起理查德·费曼所讲的轶事,他正在参加一个哲学课,教授问他"费曼,你是一个物理学家,你认为电子是一个'必不可少的对象'?" 所以费曼问澄清问题"砖块是一个必不可少的东西吗?" 上课.每个学生对这个问题都有不同的答案.他们说,"砖"的基本抽象概念是必不可少的对象.不,一个特定的,独特的砖是必不可少的对象.不,你可以凭经验观察到的砖块部分是必不可少的.等等.

这当然不是回答你的问题.

我不打算通过所有这些十几个答案,并与作者讨论我的真正含义.几个星期后我会写一篇关于这个主题的博客文章,我们会看看是否会对这个问题有所了解.

但是,费曼如何进行类比.你想在周六早上烤一条香蕉面包(就像我几乎每个星期六早上一样.)所以你咨询烹饪的喜悦,它说"等等等等......在另一个碗里,把干的成分搅拌在一起." .."

显然,明天早上该指令与你的行为之间存在着密切的关系,但同样明确的是,将指令行动混为一谈是错误的.该指令由文本组成.它在特定页面上有一个位置.它有标点符号.如果你在厨房里一起搅拌面粉和小苏打,有人问"你现在的标点是什么?",你可能认为这是一个奇怪的问题.该操作与指令有关,但指令的文本属性不是操作的属性.

演员不是转换,就像配方不是烘烤蛋糕的行为一样.配方是描述操作的文本,然后您可以执行该操作.强制转换操作符是描述操作的文本 - 转换 - 运行时可以执行该操作.

  • 我的一部分想知道与Eric合作是什么感觉.另一部分希望我在帖子中没有过多地理解他的意思. (7认同)
  • @ShelbyMooreIII:您也不会在MW中找到"struct","readonly"或"stackalloc".我不确定为什么MW定义是相关的; "转换"的相关定义在C#规范中.转换不需要改变任何东西,就像将一个数字添加到另一个数字时也不需要改变; 零是附加标识.身份转换同样是一种不会改变任何东西的转换.但是,是的,您似乎已经理解了我的观点:强制转换操作符是一个文本工件,它指示编译器生成执行转换的代码. (4认同)
  • @ShelbyMooreIII:当然,强制转换总是会导致转换。**身份转换就是转换。**但你当然可以不同意。我看到您已经写了自己的答案来解释您的立场。 (3认同)
  • @Shelby:我正忙着做家务,但你迟早应​​该能够在聊天中找到一些 C# 常客。是的,您应该停止在这里回应 - C# 的语法和术语与 C++ 的相似之处大多是肤浅的,尝试通过与其他语言的比较来回答这样的问题往往最终会让人们感到困惑。[*这个*问题可能会受益于一些历史背景](http://stackoverflow.com/questions/4337306/type-conversion-casting-confusion-in-c)。 (2认同)

Jas*_*yon 7

来自C#Spec 14.6.6:

cast-expression用于将表达式显式转换为给定类型.
...
形式为(T)E的强制转换表达式,其中T是一个类型而E是一元表达式,它执行E的值到类型T的显式转换(第13.2节).

因此,cast是一种语法结构,用于指示编译器调用显式转换.

来自C#Spec§13:

转换允许将一种类型的表达式视为另一种类型.转换可以是隐式或显式的,这决定了是否需要显式转换.[示例:例如,从int类型到long类型的转换是隐式的,因此int类型的表达式可以隐式地被视为long类型.从long类型到int类型的相反转换是显式的,因此需要显式转换.

因此,转换是实际工作完成的地方.您会注意到,cast-expression引用它表示它执行显式转换,但显式转换是隐式转换的超集,因此您也可以通过强制转换表达式调用隐式转换(即使您不需要).


Ode*_*ded 6

只是我的理解,可能太简单了:

当投射基本数据时保持不变(相同的内部表示) - "我知道这是一个字典,但你可以将它用作ICollection".

转换时,您将内部表示更改为其他内容 - "我希望此int为字符串".


Pau*_*sik 5

阅读Eric的评论之后,尝试用简单的英语:

转换意味着这两种类型在某种程度上实际上是相同的.它们可以实现相同的接口或从相同的基类继承,或者目标可以"相同"(超集?)以使转换工作,例如从Int16转换为Int32.

然后转换类型意味着两个对象可能足够相似以进行转换.以数字的字符串表示为例.它是一个字符串,它不能简单地转换为数字,需要进行解析并从一个转换为另一个,并且该过程可能会失败.它也可能因铸造而失败,但我认为这是一个更便宜的失败.

这就是我认为的两个概念之间的关键区别.转换需要对源数据进行某种解析或更深入的分析和转换.转换不解析.它只是尝试在某些多态级别进行匹配.