2013-01-09 34 views
59

Khi nói chuyện với một đồng nghiệp về C#, anh ấy đã cho tôi xem một số mã C# mà tôi đã dự đoán đầu ra của. Điều này trông đơn giản ở nơi đầu tiên, nhưng nó đã không được. Tôi không thể hiểu tại sao C# lại hành động theo cách này.hiểu các lớp chung chung lồng nhau trong C# với bài kiểm tra

Mã:

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(); 
    } 
} 

Đầu ra là:

System.Boolean 
System.Char 
System.Int32 

Đúng tôi nếu tôi sai, nhưng tôi hiểu rằng o.a là loại bool vì C<T3> thừa hưởng từ B<T3>B<T2> kế thừa từ A<T2>. Và tôi cũng có thể hiểu một chút rằng o.c thuộc loại int vì loại cT1 mà nó lấy từ lớp ngoài (tôi nghĩ).

Đầu của tôi gần như bùng nổ khi tôi cố gắng tìm ra lý do tại sao o.b thuộc loại char. Ai đó có thể giải thích điều này với tôi?

+38

Tôi rất vui vì tôi không duy trì mã tại công ty của bạn. – Default

+0

Thú vị, nhưng tổng số quá mức cần thiết cho bất cứ điều gì thực tế. Im giả định đây là học tập hơn là cho công việc? – JGilmartin

+4

@Default Tại sao? Bởi vì họ thích hỏi nhau về mã C# lạ? – Erix

Trả lời

40

Đây là một câu đố cũ, và nó là khá khó khăn. Khi tôi đưa nó cho chính Anders, lần đầu tiên anh ấy không nhận được câu trả lời!

Tôi nghĩ rằng phiên bản đồng nghiệp của bạn đưa cho bạn là từ blog Cyrus:

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

Một phiên bản hơi đơn giản hơn là trên blog của tôi.

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

Giải pháp cho phiên bản của tôi là ở đây:

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

Tóm lại, lý do cho hành vi khó hiểu là khi bạn có một cái tên mà tồn tại cả trong một lớp bên ngoài và một lớp cơ sở, lớp cơ sở "thắng". Nghĩa là, nếu bạn có:

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

Sau đó P.X.D.N thừa hưởng từ B.X, không phải từ P.X. Câu đố làm cho các kiểu chung chung lồng nhau theo cách mà cùng một khai báo có thể được đặt tên theo cả hai đường dẫn tìm kiếm "bên ngoài" và "cơ sở", nhưng có ý nghĩa khác nhau ở mỗi vì xây dựng chung.

Dù sao, hãy đọc giải thích trên các bài đăng trên blog và nếu vẫn chưa rõ, hãy đặt câu hỏi cụ thể hơn.

8

Ok, câu trả lời đầu tiên của tôi là sai. Làm tổ quan trọng:

trong o.b.GetType() b là thành viên của lớp xung quanh được khởi tạo là B<char> được kế thừa từ A<char> do đó làm cho T1 bằng char. Có gì không phải là khá rõ ràng như sau (thủ công instantiation cho 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; 
     } 
    } 
} 

Đây C_bool có thể được bắt nguồn từ A_bool.B_bool là tốt, phải không? Nhưng kể từ khi chúng tôi được lồng trong A_char được ưu tiên.

+1

Sau đó, tại sao o.c không phải là một bool? Bởi vì C kế thừa từ B mà lần lượt kế thừa từ A .. –

+1

Có gì khó hiểu là sự khác biệt giữa thừa kế và các loại kèm theo. 'C ' được đính kèm trong 'B ' nhưng kế thừa từ 'B ' – CubeSchrauber

+0

Đây là một cách hay để minh họa tình huống! –

Các vấn đề liên quan