Why does an implicit operator method in a nested class not compile?
Asked Answered
C

1

6

This code gives an error:

public class A<T>
    {
        public class B<T1> : A<T1>
        {
            public static implicit operator bool(B<T1> b) => true;
        }
    }

But if I separate the classes, there is no error:


  public class A<T> {     }

  public class B<T> : A<T>
  {
       public static implicit operator bool(B<T> b) => true;
  }
Constructivism answered 22/12, 2019 at 13:12 Comment(6)
In second case you wrote public static implicit operator bool(B<T> b), not public static implicit operator bool(A<T> b)Azerbaijani
The error is pretty clear. In the first example, you have bool(A<T> b). It should probably be bool(B<T> b).Prudential
The implicit operator in the second code snippet has a different signature - it accepts a B<T> instead of an A<T>, so the two code snippets aren't really comparable. If you change the parameter type to A<T> then it will also produce an error.Agee
@KevinGosse I fix the questionConstructivism
@Jimi, no, I edited the question, it's not workConstructivism
It's the same reason you can't type ‘new B<object>()‘, B doesn't exist in the namespace, you have to use the A... path to specify to the compiler on how to find the type.Guideboard
A
1

This is a very good question. I found that you can make the error go away by specifying A<T>.B<T1>:

public static implicit operator bool(A<T>.B<T1> b) => true;

So then I started to wonder why in this particular instance you need to qualify the inner class, because normally you don't.

Essentially, what you have written is an implicit conversion that can accept a type other than the enclosing type. Note that A<int>.B<string> and A<string>.B<string> are different classes.

Let's use a normal method, instead of an implicit conversion, to illustrate what's happening more clearly.

public class A<T>
{
    public class B<T1>
    {
        public static void F(B<T1> i) {}
    }
}

Note the absence of the inheritance clause. Bear with me for now. Here B<T1> actually means A<T>.B<T1>. This means that we can't do something like this:

A<int>.B<string>.F(new A<string>.B<string>()); // cannot convert type ...

So it would seem just writing B<T1> in the conversion would work. But when you introduce the inheritance clause...

public class A<T>
{
    public class B<T1>: A<T1>
    {
        public static void F(B<T1> i) {}
    }
}

A<int>.B<string>.F(new A<string>.B<string>()); // suddenly this compiles

This means that you can now pass something else other than A<T>.B<T1> to the implicit conversion, and that is not allowed.

Agee answered 22/12, 2019 at 14:8 Comment(6)
Thank you for the answer, I think that there is compiler trick, but I don't understand how it's workConstructivism
@EvgeniyTerekhin you don’t understand what? If you clarify I might be able to explain.Agee
I don't understand why the compiler bind parameter "i" in "Foo" method as A<T1>.B<T1>. Why is it not A<T>.B<T1>?Constructivism
i is A<T>.B<T1>. I never said it is otherwise. @EvgeniyTerekhinAgee
when I use inheritance, i is A<T1>.B<T1>,without inheritance i is A<T>.B<T1>Constructivism
No, i is always of type A<T>.B<T1>. But with inheritance, you become able to pass objects of type A<T1>.B<T1> into i, i.e. there now exists a reference conversion from A<T1>.B<T1> to A<T>.B<T1>. As to why that is the case... I still cannot explain. But the immediate reason to why your code doesn't compile is "because you can pass something other than A<T>.B<T1> into the conversion". Maybe you can ask another question for that? @EvgeniyTerekhinAgee

© 2022 - 2024 — McMap. All rights reserved.