2013-02-13 30 views
8

Tôi hy vọng câu hỏi là chính xác, vì vậy hãy cho bạn một ví dụ. Hãy tưởng tượng các phương pháp chung như sau:Tại sao VS cảnh báo tôi rằng typeof (T) không bao giờ là loại được cung cấp trong một phương pháp chung mà tham số kiểu bị hạn chế để thực hiện T?

public abstract class Base : IDisposable 
{ 
    public static IEnumerable<T> GetList<T>() 
     where T : Base 
    { 
     // To ensure T inherits from Base. 
     if (typeof(T) is Base) 
      throw new NotSupportedException(); 

     // ... 
    } 
} 

Theo MSDN từ khóa where hạn chế tham số kiểu T là loại Base hoặc kế thừa từ lớp này.

[...] mệnh đề where có thể bao gồm ràng buộc lớp cơ sở, cho biết loại phải có lớp được chỉ định làm lớp cơ sở (hoặc chính lớp đó) để được sử dụng làm loại đối số cho loại chung đó.

Ngoài ra mã này không biên dịch:

public static T GetFirst() 
    where T : Base 
{ 
    // Call GetList explicitly using Base as type parameter. 
    return (T)GetList<Base>().First(); 
} 

Vì vậy, khi sau mã cuối cùng typeof(T) nên trở Base, không nên nó? Tại sao Visual Studio sau đó in cảnh báo này cho tôi?

cảnh báo CS0184: Biểu thức đã cho không bao giờ được cung cấp (loại 'Demo.Base').

+0

Bạn muốn làm gì? Đảm bảo rằng 'T' kế thừa từ' Base' là vô ích, vì hạn chế chung đã đảm bảo điều đó. – CodesInChaos

+0

Ràng buộc đảm bảo rằng 'T' hoặc kế thừa từ' Base' ** OR ** là 'Base'. Tôi muốn 'T' chỉ kế thừa từ' Base'. – Carsten

Trả lời

13

typeof(whatever) luôn trả về phiên bản loại Type. Type không xuất phát từ Base.

Những gì bạn muốn là thế này:

if(typeof(T) == typeof(Base)) 
    throw new NotSupportedException("Please specify a type derived from Base"); 

Cái gì đó có vẻ như nó là như nhau là thế này:

if(variableOfTypeT is Base) 

Nhưng điều đó có một ý nghĩa khác nhau.
Tuyên bố đầu tiên (với typeof(Base)) chỉ là true nếu TBase. Nó sẽ là false đối với mọi loại có nguồn gốc từ Base.
Câu lệnh thứ hai (variableOfTypeT is Base) luôn là true trong lớp học của bạn, bởi vì mọi lớp học có nguồn gốc từ Base sẽ trả lại true để kiểm tra lớp cơ sở của nó.

+0

Phương án thay thế không hoạt động ... 'T' là một tham số kiểu nhưng được sử dụng như một biến;) Nhưng cách tiếp cận đầu tiên hoạt động ... Làm thế nào tôi bỏ lỡ điều đó ?! Đôi khi giải pháp quá đơn giản: D – Carsten

+0

@Aschratt: Bạn nói đúng, tôi đã sửa lại điều đó. –

1

Đó không phải là cách bạn kiểm tra thừa kế.

typeof(T) thuộc loại System.Type, không phải là Base. Để xem liệu T có bắt nguồn từ Cơ sở hay không, bạn nên sử dụng số IsSubclassOf method, như sau:

if(typeof(T).IsSubclassOf(typeof(Base)) ... 
+0

Lưu ý rằng sẽ trả về 'false' nếu' T == Base' – CodesInChaos

+0

Tôi nghĩ đó là vấn đề. Do hạn chế, OP đã biết T là Base hoặc bắt nguồn từ nó. – zmbq

+0

Tôi muốn biết nếu 'T' * là *' Base' để đảm bảo chỉ việc triển khai lớp trừu tượng đó mới được chuyển cho phương thức. 'IsSubclassOf' sẽ thực hiện kiểm tra mà tôi đã thể hiện với ràng buộc' where'. – Carsten