2011-08-12 41 views
5

Tôi có một phương thức lấy một tham số chung T. Bên trong, để quyết định phương thức nào cần gọi, tôi cần biết (không ràng buộc nó) nếu tham số đó là một Danh sách hoặc chỉ một cái gì đó.Loại danh sách chung của tôi là một danh sách hay chỉ là một mục?

Tôi làm như thế nào?

Tôi đã sử dụng

var isList = typeof(T).Name.ToLower().Contains("list`1"); 

nhưng mà cảm thấy như một cách tiếp cận bẩn. Cái gì sạch hơn?

+0

Bạn đã thử so sánh nó với một loại đối tượng danh sách khác không? – krs1

+1

Điều này sẽ thất bại nếu bạn vượt qua nó một ví dụ 'NotReallyAList '. –

+0

* Chính xác * ý của bạn là gì khi bạn nói "danh sách"? Bạn có nghĩa là loại chính xác 'System.Collections.Generic.List '? Hoặc bạn có nghĩa là bất cứ điều gì với 0 hoặc nhiều mặt hàng? Hoặc bất kỳ loại bộ sưu tập nào có thể đọc cũng như được cập nhật? v.v. – stakx

Trả lời

11
var type = typeof(T); 
bool isList = type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>); 

Nếu bạn không cần khớp chính xác cho Danh sách, bạn cũng có thể kiểm tra xem typeof(IList).IsAssignableFrom(typeof(T)) có nhiều bộ sưu tập giống như danh sách hay không.


Nếu bạn muốn hỗ trợ T là bằng IList<T2> trực tiếp (vì vậy các loại tham số T là một giao diện), sau đó bạn cần phải kiểm tra cho rằng riêng (GetGenericTypeDefinition() cũng có thể trở lại typeof(IList<>)).

Nếu bạn muốn hỗ trợ mọi loại T kế thừa từ bất kỳ IList<>, thì bạn phải sáng tạo hơn một chút. Bạn phải liệt kê tất cả các giao diện, kiểm tra xem chúng có chung chung không (như trên) và sau đó kiểm tra xem kiểu chung của giao diện là IList<> hay không. Ngoài ra, do cuộc gọi GetInterfaces() trên Type chỉ trả về các giao diện cấp cao nhất, bạn cần điều hướng qua tất cả các giao diện được thực hiện bởi mỗi giao diện (đệ quy), để kiểm tra các giao diện đó. Xấu xí, tôi biết.

+1

+1 bởi vì nó trả lời câu hỏi. Như một lưu ý phụ, nếu có một số chức năng phổ biến theo sau sự phản ánh để xử lý tiếp theo dựa trên loại, bạn có thể muốn thực hiện một phương thức 'Process (List item)' với quá tải cho mỗi khả năng. Hãy để trình biên dịch xử lý việc xử lý tiếp theo mà không cần phản ánh. Mặc dù, điều này có thể không được áp dụng trong tình huống này (không rõ ràng nếu 'Danh sách ' là khả năng duy nhất khác). –

+0

Tôi thích những gì bạn đang nhận được trong đoạn mã - nhưng tôi nhận được sai mỗi lần. Tôi đang chuyển một IList làm T, và vẫn không thành công. Cách tiếp cận thứ hai mang lại cho tôi những vấn đề tương tự. – reallyJim

+0

Chấp nhận câu trả lời này vì câu trả lời hoàn toàn trả lời câu hỏi của tôi và giải quyết vấn đề của tôi - bao gồm liệt kê các giao diện để tìm IList <>. Cảm ơn! – reallyJim

0

Kiểm tra xem nó có triển khai giao diện IEnumerable hay không.

bool isList = T is IEnumerable; 

Điều này cũng sẽ trả về true nếu T là Ngăn xếp, Mảng hoặc những thứ khác, nhưng tôi nghĩ nó sẽ đủ cho mục đích của bạn.

+0

Điều này sẽ không biên dịch. – Gabe

+0

Điều này sẽ không biên dịch. 'T' là 'tham số kiểu' nhưng được sử dụng như một biến. – reallyJim

+0

Bạn cần thêm 'typeof (T)' như trong ví dụ của tôi. – Gabe

2

Vâng, bạn luôn có thể sử dụng typeof(T) và từ khóa is, nhưng tôi sẽ xem xét lại thiết kế của bạn.

Cách tiếp cận của bạn thực sự đang đánh bại mục đích của một phương pháp chung. Nếu bạn phải kiểm tra kiểu của đối số chung, tốt, phương pháp của bạn không phải là chung chung. Generics là tuyệt vời cho các kịch bản mà bạn không quan tâm những gì loại cơ bản là. Nếu bạn quan tâm thì phương pháp này không nên là chung chung, nó sẽ bị quá tải (có thể). Làm thế nào abut nói với chúng tôi những gì bạn đang thực sự cố gắng để thực hiện ở đây để chúng tôi có thể cung cấp cho phản ứng hữu ích hơn?

+0

Bạn thực sự không muốn biết. :) Tôi đang tạo một đối tượng truy vấn cơ sở với một phương thức để gọi NHibernate's ISqlQuery.List() hoặc ISqlQuery.UniqueResult - trả về kết quả của SPROC như là một kiểu động. Thay vì dùng cách tiếp cận "biết" trước, và yêu cầu mã gọi để gọi "duy nhất" hoặc "danh sách", tôi muốn giúp các nhà phát triển bằng cách đưa ra quyết định đó ở mặt sau. – reallyJim

+1

@reallyJim: Kinda giống như [Massive] (https://github.com/robconery/massive)? –

+0

@jim Schubert Có - đã không nhận ra tôi đã nhận được rằng gần như tái phát minh bánh xe. Gốc của vấn đề là tôi phải đối phó với SPROCs trả về kết quả mà tôi cần phải chuyển đổi sang đối tượng kinh doanh của tôi - nhưng tôi không muốn tạo ánh xạ cho. – reallyJim

0

Nếu bạn đang tìm kiếm bất kỳ bộ sưu tập tích hợp nào, bạn sẽ kiểm tra IEnumerable. Bằng cách đó bạn không cần phải lo lắng về tham số kiểu. Tuy nhiên điều này đặt ra một vấn đề bởi vì chuỗi thực hiện IEnumerable. Do đó, bạn sẽ cần một số mã như sau:

if (typeof(T) is string) { 
} else if (typeof(T) is IEnumerable) { 
} else { // its something else 
} 
+0

Tùy thuộc vào sự hiểu biết về danh sách có nghĩa là gì, 'IEnumerable' có thể bao gồm quá nhiều thứ. Ví dụ, không giống như 'IList', một' IEnumerable' của chính nó là độc quyền chỉ đọc: tôi có thể ví dụ: thực hiện một lớp 'IEnumerable' trả về dãy Fibonacci. Bạn sẽ xem xét một trường hợp của lớp đó một danh sách? – stakx

+0

@stakx - điểm tốt, tôi đã cập nhật câu trả lời của mình. –

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