继承和泛型类型设置

Bac*_*ave 5 c# generics inheritance

有人可以向我解释为什么下面的代码会输出它的作用吗?为什么T是一个字符串在第一个,而不是Int32,为什么在下一个输出中它是相反的情况?

这个谜题来自对Eric Lippert采访

当我浏览代码时,我真的不知道它是Int32还是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();
        }
    }
Run Code Online (Sandbox Code Playgroud)

Eri*_*ert 5

有人可以向我解释为什么下面的代码会输出它的作用吗?

问题的关键在于确定Bin 的含义class C : B.考虑一个没有泛型的版本:(为简洁起见,我将省略公众.)

class D { class E {} }
class J {
  class E {}
  class K : D {
    E e; // Fully qualify this type
  }
}
Run Code Online (Sandbox Code Playgroud)

那可能是J.ED.E; 这是什么?解析名称时C#中的规则是查看基类层次结构,只有当它失败时,才能查看容器.K已经通过继承拥有成员E,因此不需要查看其容器以发现其容器具有包含成员E.

但是我们看到这个谜题具有相同的结构; 它只是被仿制药混淆了.我们可以像处理模板那样处理泛型,只需将A-of-string和A-of-int的结构写成类:

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
  }
}
Run Code Online (Sandbox Code Playgroud)

现在应该清楚为什么A_of_string.B.M()stringA_of_string.B.C.M()int.


小智 2

稍微改变一下代码:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意我如何将C基类从更改BA<T>.B。这会将输出从 更改System.Int32System.String

如果没有它,A<string>.B.C不是从 派生A<string>.B,而是从 派生A<int>.B,导致您所看到的行为。这是因为,一般来说,基类中定义的名称可以通过非限定查找来获得,并且该名称B是在基类中定义的A<int>