2011-01-04 42 views
34

về cơ bản tôi đang xây dựng một mẫu T4 rất chung chung và một trong những điều tôi cần làm là nói in variable.ToString(). Tuy nhiên, tôi muốn nó để đánh giá danh sách và foreach thông qua họ và thay vì in ListItem.ToString() mẫu T4 của tôi không biết loại variable sẽ được trước thời hạn, đó là lý do tại sao điều này là như vậy chung chung.Làm thế nào để kiểm tra xem một biến là một số IEnumerable của một số loại

Nhưng mã hiện tại của tôi mà được tạo ra trông như sau:

if(variable!=null) 
    if(variable is IEnumerable) //error here 
    foreach(var item in variable) 
     Write(item.ToString()); 

tôi nhận được một lỗi biên dịch trên dòng rõ rệt cho "Sử dụng kiểu generic System.Generic.Collections.IEnumerable đòi hỏi một loại lập luận"

Tôi không thực sự quan tâm đó là loại mặc dù, tôi chỉ muốn biết nếu bạn có thể foreach thông qua các biến. Tôi nên sử dụng mã nào?

Trả lời

48

Tuy nhiên, bạn đã chấp nhận câu trả lời, vì việc chung chung IEnumerable<T> thực hiện không chung chung IEnumerable bạn chỉ có thể truyền tới điều đó.

// Does write handle null? Might need some sanity aswell. 

var enumerable = variable as System.Collections.IEnumerable; 

if (enumerable != null) 
    foreach(var item in enumerable) 
     Write(item); 
else 
    Write(item);  
+0

Có vẻ như đây có thể là câu trả lời hay hơn. – Earlz

+0

Tôi đã thay đổi câu trả lời vì tôi đã sử dụng phương pháp này, theo ý kiến ​​của tôi thì sạch sẽ hơn nhiều. – Earlz

+0

Ngoài ra, để có được xung quanh lỗi Mono được đề cập dưới đây, tôi đã phải đúc 'biến' vào một' đối tượng' đầu tiên. – Earlz

16

Nếu bạn muốn thử nghiệm cho số IEnumerable không chung chung thì bạn sẽ cần phải bao gồm chỉ thị using System.Collections ở đầu tệp nguồn của bạn.

Nếu bạn muốn kiểm tra cho một IEnumerable<T> của một số loại thì bạn sẽ cần một cái gì đó như thế này thay vì:

if (variable != null) 
{ 
    if (variable.GetType().GetInterfaces().Any(
      i => i.IsGenericType && 
      i.GetGenericTypeDefinition() == typeof(IEnumerable<>))) 
    { 
     // foreach... 
    } 
} 
+0

Tôi đã sử dụng ở đầu tệp nguồn của mình. – Earlz

+0

@Earlz 'System.Collections.Generic'!= 'System.Collections' - lỗi trong bài viết là dấu hiệu của việc không tìm thấy loại không chung chung (IEnumerable). –

+0

Heh, tôi sử dụng này và Mono tát tôi với 'mã IL không hợp lệ trong EViewEngine.TestView: BuildOutput(): IL_0105: castclass 0x1b000002' Hmm thật thú vị. – Earlz

2

Trong chung, không có không chung chung kiểu cơ sở/giao diện, điều này đòi hỏi GetType và tìm kiếm đệ quy thông qua các loại/giao diện cơ sở.

Tuy nhiên, điều đó không áp dụng ở đây :-) Chỉ cần sử dụng non-generic IEnumerable (System.Collections.IEnumerable), từ đó generic IEnumerable (System.Collections.Generic.IEnumerable<T>) được thừa hưởng.

1

Vâng, hơi đơn giản nhưng ... nếu bạn chỉ có:

using System.Collections.Generic; 

bạn có thể cần phải thêm:

using System.Collections; 

Các định nghĩa cựu IEnumerable<T> và sau định nghĩa IEnumerable.

14

Các câu trả lời khác đã chỉ ra sự khác biệt chung của IEnumerable nhưng tôi cũng nên chỉ ra rằng bạn cũng sẽ muốn kiểm tra chuỗi cụ thể bởi vì nó thực hiện IEnumerable nhưng tôi nghi ngờ bạn sẽ muốn coi nó như là một bộ sưu tập các nhân vật.

0

Đây là một câu hỏi cũ, nhưng tôi muốn thể hiện một phương pháp khác để xác định liệu SomeTypeIEnumerable:

var isEnumerable = (typeof(SomeType).Name == "IEnumerable`1"); 
0

Bạn thực sự có thể kiểm tra các lớp cơ sở của bất kỳ loại generic trực tiếp.

instance.GetGenericTypeDefinition() == typeof(IEnumerable<>) 
Các vấn đề liên quan