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修正C<T3>B<T3>B<T2>くださいA<T2>o.cまた、型が int であるcことも少し理解できます。これは、型T1が外部クラスから取得されるためです (と思います)。

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.XP.X

とにかく、ブログ投稿の説明を読んで、それでも明確でない場合は、より具体的な質問をしてください。

于 2013-01-09T15:26:18.877 に答える
8

わかりました、私の最初の答えは間違っていました。ネストは重要です。

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 に答える