60

在与一位同事谈论 C# 时,他向我展示了一些 C# 代码,我必须预测其输出。这首先看起来很简单,但事实并非如此。我真的不明白为什么 C# 会这样。

编码:

public class A<T1>
{
    public T1 a;

    public class B<T2> : A<T2>
    {
        public T1 b;

        public class C<T3> : B<T3>
        {
            public T1 c;
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        A<int>.B<char>.C<bool> o = new A<int>.B<char>.C<bool>();

        Console.WriteLine(o.a.GetType());
        Console.WriteLine(o.b.GetType());
        Console.WriteLine(o.c.GetType());

        Console.ReadKey();
    }
}

输出是:

System.Boolean
System.Char
System.Int32

如果我错了,请纠正我,但我知道这o.a是 bool 类型,因为C<T3>继承自B<T3>B<T2>继承自A<T2>. 而且我也可以稍微理解它o.c是 int 类型,因为它的类型cT1从外部类中获得的(我认为)。

当我试图弄清楚为什么o.b是 char 类型时,我的脑袋几乎要爆炸了。谁可以给我解释一下这个?

4

2 回答 2

40

这是一个古老的谜题,而且相当困难。当我把它给安德斯本人时,他第一次没有得到正确的答案!

我认为您的同事给您的版本来自 Cyrus 的博客:

http://blogs.msdn.com/b/cyrusn/archive/2005/08/01/446431.aspx

我的博客上有一个稍微简单的版本。

http://blogs.msdn.com/b/ericlippert/archive/2007/07/27/an-inheritance-puzzle-part-one.aspx

我的版本的解决方案在这里:

http://blogs.msdn.com/b/ericlippert/archive/2007/07/30/an-inheritance-puzzle-part-two.aspx

简而言之,令人困惑的行为的原因是,当您的名称同时存在于外部类和基类中时,基类“获胜”。也就是说,如果您有:

public class B
{
  public class X {}
} 
public class P
{
  public class X
  {
    public class D : B
    {
      public class N : X {}
    }
  }
}

然后P.X.D.N继承自B.X,而不是继承自P.X。这个谜题以这样一种方式使嵌套的泛型类型可以通过“外部”和“基本”搜索路径命名相同的声明,但由于泛型构造,它们在每个路径中具有不同的含义。

无论如何,请阅读博客文章上的解释,如果仍然不清楚,请提出更具体的问题。

于 2013-01-09T15:26:18.877 回答
8

好吧,我的第一个答案是错误的。嵌套很重要:

in o.b.GetType()b 是周围类的成员,它被实例化为B<char>它继承自A<char>它反过来使 T1 等于 char。不太清楚的是以下内容(手动实例化A_int.B_char.C_bool):

public class A_bool
{
    public bool a;

    public class B_bool : A_bool
    {
        public bool b;
    }
}

public class A_char
{
    public char a;

    public class B_bool : A_bool
    {
        public char b;
    }
}

public class A_int
{
    public int a;

    public class B_char : A_char
    {
        public int b;

        public class C_bool : A_char.B_bool
        {
            public int c;
        }
    }
}

这里C_bool也可以从 A_bool.B_bool 派生,对吗?但既然我们嵌套在A_char其中,那就是首选。

于 2013-01-09T14:57:24.213 回答