1

Suppose I have a struct and a class with the same members:

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;
        }
    }
}

So in short, the members are the same, but the class defines implicit conversion methods to and from the struct.

This code happily compiles as is even though I didn't specify how the values should be converted. My first thought was "The member names/types are the same, so the compiler must be able to figure it out"...

..., but then I changed one of the member's return type from int to string and renamed it leaving no trace of the original name, the code still compiled fine.

Please explain the behaviour to me. (Does the environment try to "copy" as many members as possible?)

I use the latest .Net framework in VS 2017 Community

Aldert
  • 4,209
  • 1
  • 9
  • 23
nurchi
  • 770
  • 11
  • 24
  • 1
    Did you try testing these operators? What happened when you try to convert from class to struct and vice versa? – Chetan Sep 15 '18 at 06:19
  • I ran your code, it is not working. appropriate message for this site:-) System.StackOverflowException: 'Exception of type 'System.StackOverflowException' was thrown.' – Aldert Sep 15 '18 at 06:55
  • Possible duplicate of [If two objects have same properties, can the values from one be autoassigned?](https://stackoverflow.com/questions/20410234/if-two-objects-have-same-properties-can-the-values-from-one-be-autoassigned) – mjwills Sep 15 '18 at 07:47

1 Answers1

7

It's an unfortunate circumstance. The code compiles but is useless:

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

When the compiler gets to the return f;, it effectively says "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".

As with many other cases of unintended recursion1, the simple cases are easy to spot, and the compiler could probably be made smart enough to spot them, but then you'd hit an arbitrary cutoff point beyond which it's not possible to spot the infinite recursion during compilation2. And inconsistent errors/warnings tend to be frowned upon (less predictable language).

Thankfully, code like this never tends to make it to production since the stack overflows tend to be spotted as soon as testing begins.


1A common one that's bitten a lot of people at some point is to attempt to implement a property in terms of itself rather than using its backing field, but that's maybe a less encountered situation these days with auto-implemented properties being more normal.

2Insert standard references to the halting problem, etc.

Damien_The_Unbeliever
  • 234,701
  • 27
  • 340
  • 448
  • Thanks. I wouldn't have thought of that (maybe I would if I had debugged the one line I have in there :P). This explains StackOverflowException that Aldert mentioned in his comment to my question. I had similar issues when overloading `Equals` and the `==` and `!=` operators, just didn't put 2 and 2 together. Thanks again for an awesome explanation (esp. the part about 'some kindly soul has provided an implicit operator...' :D). – nurchi Sep 17 '18 at 03:00