2013-08-08 34 views
10

Ở đây chúng ta có một herarchy lớp đơn giản, và sử dụng Generics với một type constraint của new()Generic loại chế mới() và một cơ sở trừu tượng lớp

public abstract class Base 
{ 
} 

public class Derived : Base 
{ 
} 

public class TestClass 
{ 
    private void DoSomething<T>(T arg) where T : new() 
    { 
    } 

    public void TestMethod() 
    { 
     Derived d1 = new Derived(); 
     DoSomething(d1); // compiles 

     Base d2 = new Derived(); 
     DoSomething(d2); // compile error 
    } 
} 

Mã này thất bại trong việc biên dịch tại dòng chỉ định, với lỗi của:

'cơ sở' phải là một loại phi trừu tượng với một constructor parameterless nào để sử dụng nó như là tham số 'T' trong các loại generic hoặc phương pháp 'Foo.DoSomething (T)'

Lỗi này là rõ ràng và có ý nghĩa, nhưng tôi đã hy vọng rằng trình biên dịch sẽ hiểu rằng tất cả các dẫn xuất của Base (có thể được khởi tạo tại thời điểm này) không có một constructor công khai parameterless.

Điều này có thể về lý thuyết cho trình biên dịch không?

+0

Đó là dòng này khiến tôi lo lắng hơn 'loại không trừu tượng' hơn mệnh đề hàm tạo ít tham số –

Trả lời

8

Alas bạn phải rõ ràng cho loại

DoSomething<Derived>(d2); 

về mặt lý thuyết là không thể tạo ra một cái gì đó trừu tượng

+5

Tôi thích phần" về mặt lý thuyết ". Làm cho tôi cảm thấy như Jon Skeet sẽ bật, làm một số phép thuật, và có bạn đi, instantiated đối tượng trừu tượng. –

+0

Phiên bản .NET nào sẽ biên dịch nếu d2 được khai báo là Cơ sở trừu tượng? –

1

new Constraint (C# Reference):

Để sử dụng các hạn chế mới, loại không thể trừu tượng.

Calling:

Base d2 = new Derived(); 
DoSomething(d2); 

Bạn đang trên thực tế thực hiện:

Base d2 = new Derived(); 
DoSomething<Base>(d2); 

Kể từ khi Base là trừu tượng, lỗi biên dịch xảy ra.

Vì vậy, bạn phải bỏ một cách rõ ràng:

Base d2 = new Derived(); 
DoSomething((Derived) d2); 

Làm thế nào bạn có thể đảm bảo trình biên dịch, mà bất cứ ai từng đặt ở đó một cái gì đó, đó không phải là trừu tượng?

Cách duy nhất tôi thấy sẽ là, nếu chúng tôi có từ khóa như "phải thừa kế-không-trừ" và sau đó tạo public must-inherit-to-non-abstract abstract class Base. Sau đó, trình biên dịch có thể chắc chắn, rằng nếu bạn đặt cá thể cơ sở vào phương thức của bạn, đó sẽ là một lớp con, đó là không trừu tượng và do đó có thể được khởi tạo.

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