代码之家  ›  专栏  ›  技术社区  ›  Tara McGrew

为什么我需要一个中间转换来从结构转换为十进制,而不是从结构转换为int?

  •  8
  • Tara McGrew  · 技术社区  · 16 年前

    我有一个这样的结构,它有一个到float的显式转换:

    struct TwFix32
    {
        public static explicit operator float(TwFix32 x) { ... }
    }
    

    我可以使用单个显式转换将twfix32转换为int: (int)fix32

    但要将其转换为十进制,我必须使用两种转换: (decimal)(float)fix32

    不存在从float到int或decimal的隐式转换。当我准备int时,为什么编译器会让我省略中间强制转换以浮动,而当我准备decimal时却不这样做?

    1 回复  |  直到 16 年前
        1
  •  8
  •   Eric Lippert    16 年前

    对于“为什么”的问题,我常常不知所措地给出一个令人满意的答案。

    C编译器表现出这种行为的原因是(在本例中,至少是(*) 正确执行C规范 .

    本规范第6.4.5节描述了如何分析用户定义的转换。仔细阅读这一节将解释为什么显式转换为int是合法的,而转换为decimal是不合法的。

    具体而言,相关段落是:

    查找一组适用的用户定义的和提升的转换运算符,u。该组由用户定义的和提升的隐式或显式转换运算符组成,这些隐式或显式转换运算符由d中的类或结构声明,这些类或结构从包含s或包含s的类型转换为包含t或包含t的类型。如果u为空,则转换为未定义的出现编译时错误。

    在您的例子中,s是twfix,t是in t或decimal。twfix上唯一的用户定义的显式转换返回一个浮点。int包含在float中,但decimal既不包含在float中,也不包含在float中。因此集合U在一种情况下有一个成员,在另一种情况下是空的。因此,正如规范所说,一种情况会产生错误,而另一种情况则不会。

    我觉得这个答案不令人满意。如果没有,你能把这个问题改成没有“为什么”这个词的形式吗?我在回答“什么”或“如何”问题上比回答“为什么”问题好得多。

    (*)编译器在代码中已知错误,该代码计算一种类型是否包含另一种类型,以便在分析特定用户定义转换的语义时确定哪些内置转换是相关的。在许多情况下,我们故意不修复这些bug,因为这样做会导致实际代码发生重大更改,而不会带来任何好处。我非常希望重新阅读规范的这一部分,并重写它,以便删除“包含类型”的概念;它在规范中有点奇怪。正如您所发现的,它产生了这种奇怪,其中float可显式转换为decimal,decimal可显式转换为float,但由于两者都不包含另一方面,用户定义的显式转换代码不喜欢它。然而,这是非常低的优先级。