Inheritance and general type of customization

Can someone explain to me why the code below outputs what it does? Why is T a string in the first, not Int32, and why is the opposite case in the next output?

This puzzle is from an interview with Eric Lippert

When I look at the code, I really have no idea whether it will be Int32 or String:

public class A<T>
    {
        public class B : A<int>
        {
            public void M() { System.Console.WriteLine(typeof(T)); }
            public class C : B { }
        }
    }

    public class P
    {
        public static void Main()
        {            
            (new A<string>.B()).M(); //Outputs System.String
            (new A<string>.B.C()).M(); //Outputs System.Int32
            Console.Read();
        }
    }
+4
source share
5 answers

Change the code a bit:

public class A<T>
{
    public class B : A<int>
    {
        public void M() { System.Console.WriteLine(typeof(T)); }
        public class C : A<T>.B { }
    }
}

public class P
{
    public static void Main()
    {            
        (new A<string>.B.C()).M(); //Outputs System.String
    }
}

Notice how I changed the base class Cfrom Bto A<T>.B. This changes the output from System.Int32to System.String.

A<string>.B.C A<string>.B, A<int>.B, , . , , , , B A<int>.

+2

M B typeof(T) A<T>, A B.

, , B -, M typeof(T), String.

A<T>.B.M A T.

, A<string>.B.M String

A<string>.B.C, A<string>.B.A<int>.B ( C A<int>.B), A<string>.B.A<int>.B.M T.

A<string>.B.A<int>.B.M int

+4

Generics T . B, A. , C B, T B C. , T B - int, , C, int .

+3

M() :

, (new A<string>.B.C()).M(); B, int. ( , B A<int>)

(new A<string>.B()).M(); string, B A<string>.

+3

- , , ?

B class C : B. : ( .)

class D { class E {} }
class J {
  class E {}
  class K : D {
    E e; // Fully qualify this type
  }
}

J.E D.E; ? # - , , . K E , , , E .

But we see that the puzzle has the same structure; it's just getting confused by generics. We can consider the generic one as a template, and simply write out the A-of-string and A-of-int constructions as classes:

class A_of_int 
{
  class B : A_of_int
  {
    void M() { Write("int"); }
    class C : B { } // A_of_int.B
  }
}
class A_of_string
{
  class B : A_of_int
  {
    void M() { Write("string"); }
    class C : B {} // still A_of_int.B
  }
}

And now it should be clear why he A_of_string.B.M()writes string, but he A_of_string.B.C.M()writes int.

+3
source

Source: https://habr.com/ru/post/1664823/


All Articles