结构到 class 并返回隐式转换

Struct to class and back implicit conversion

假设我有一个结构和一个 class 具有相同的成员:

using System;

class app
{
    static void Main()
    {
        foo f = new foo() { a  = 4, b = 7 };
        bar b = f;
        Console.WriteLine(b.a);
        Console.ReadKey();
    }

    struct foo
    {
        public int a { get; set; }
        public uint b { get; set; }
    }

    class bar
    {
        public int a { get; set; }
        public uint b { get; set; }

        public static implicit operator foo(bar b)
        {
            return b;
        }

        public static implicit operator bar(foo f)
        {
            return f;
        }
    }
}

所以简而言之,成员是相同的,但是 class 定义了与结构之间的隐式转换方法。

即使我没有指定值的转换方式,这段代码也能顺利编译。我的第一个想法是 "The member names/types are the same, so the compiler must be able to figure it out"...

...,但后来我将其中一个成员的 return 类型从 int 更改为 string 并重命名它,没有留下原始名称的痕迹,代码仍然编译很好。

请向我解释一下这个行为。 (环境是否尝试 "copy" 尽可能多的成员?)

我在 VS 2017 Community 中使用最新的 .Net 框架

这是一个不幸的情况。代码编译但没用:

public static implicit operator bar(foo f)
{
    return f;
}

当编译器到达 return f; 时,它实际上表示 "I've got a foo in this return statement, but I'm meant to return a bar. Hmm. That's okay, because some kindly soul has provided an implicit operator that converts foo to bar, I'll call that conversion operator here"。

与许多其他意外递归情况一样1简单情况很容易发现,编译器可能聪明到可以发现它们,但是你会遇到一个任意的截止点,超过这个点就不可能在编译期间发现无限递归2。不一致的 errors/warnings 往往会让人皱眉(不太可预测的语言)。

值得庆幸的是,这样的代码永远不会投入生产,因为一旦测试开始就会发现堆栈溢出。


1很多人在一些点被咬的一个常见的是尝试在属性中实现本身的条款而不是使用其支持字段,但现在这种情况可能很少遇到,因为自动实现的属性更加正常。

2插入对停机问题等的标准引用