2016-07-22 23 views
7

tôi có mã này:lỗi C# 6? ảo phương pháp mới lạ hành vi

using System; 

namespace Test 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Foo foo = new Foo(); 
      Bar bar = new Bar(); 
      Baz baz = new Baz(); 
      Foo fooBar = new Bar(); 
      Foo fooBaz = new Baz(); 
      Bar barBaz = new Baz(); 

      foo.Test(); 
      bar.Test(); 
      baz.Test(); 
      fooBar.Test(); 
      fooBaz.Test(); 
      barBaz.Test(); 

      Console.ReadLine(); 
     } 
    } 

    internal class Foo 
    { 
     public virtual void Test() 
     { 
      Console.WriteLine("Foo"); 
     } 
    } 

    internal class Bar : Foo 
    { 
     public new virtual void Test() 
     { 
      Console.WriteLine("Bar"); 
     } 
    } 

    internal class Baz : Bar 
    { 
     public override void Test() 
     { 
      Console.WriteLine("Baz"); 
     } 
    } 
} 

nó ra tôi:

Foo 
Bar 
Baz 
Foo 
Foo 
Baz 

Nhưng, tôi nghĩ rằng nó nên là:

Foo 
Bar 
Baz 
Foo 
Baz 
Baz 

Vì Baz được trọng các phương pháp. Chuyện gì đang xảy ra ở đây? Tôi có thiếu gì đó không? Tại sao đầu ra cho fooBaz.Test() là "Foo" thay vì "Baz"?

Trả lời

2

Khi bạn sử dụng từ khóa mới trên Bar.Test, bạn đang nói rằng từ khóa không có liên quan đến Foo.Test khác với tên đó có cùng tên. Vì Baz kế thừa từ Bar, nó ghi đè Bar.Test nhưng để lại Foo.Test chưa được sửa đổi.

Khi bạn gọi fooBaz.Test, hãy tìm phương thức Foo.Test chưa sửa đổi và in "Foo".

Khi bạn gọi barBaz.Test, hãy tìm phương pháp được ghi đè lên số Bar.Test và in "Baz".

5

Buz được trọng phương pháp, đó là lý do tại sao

Bar barBaz = new Baz(); 
barBaz.Test(); 

sẽ in Baz.

Nhưng Bar không ghi đè - đó là ẩn phương thức cơ sở Test và làm cho phương pháp mới ảo. Sau đó, Baz sẽ ghi đè phương pháp mới từ Bar, không phải phương thức từ Foo. Vì vậy, nếu bạn tham khảo nó như thế này: Foo fooBaz = new Baz(); sau đó fooBaz được xử lý như một thể hiện của Foo, mà không có ý tưởng về phương pháp ẩn.

Kết quả bạn mong đợi sẽ được tạo nếu bạn thay đổi public new virtual void Test() thành public override void Test().

Xem thêm các chủ đề này:

+0

chính xác, Baz được trọng phương pháp này. Baz nên được xem xét đầu tiên bởi trình biên dịch, phải không? –

+0

Jon Skeet nên giải thích điều này, bởi vì tôi vẫn không hiểu, hahahah –