2012-07-11 31 views
18

Tôi đang rối tung với các generics và IEnumerable abit, nhưng tôi bị mắc kẹt. Đây là những gì tôi đang cố gắng làm: Tôi muốn có phương thức trả về bất kỳ loại bộ sưu tập nào - triển khai IEnumerable (?) - (ví dụ: Danh sách, Ngăn xếp, Hàng đợi, ...)trả về một số chung IEnumerable <T>

hơn nữa, tôi muốn có thể trả về bất kỳ loại bộ sưu tập nào, của bất kỳ kiểu dữ liệu nào. vì vậy tôi muốn phương pháp này để có thể trả về một List<string>, cũng như một Stack<int>, cũng như một List<double> ... vv vv

public IEnumerable<T> returnSomething() 
    { 
     Stack<int> stackOfInts = new Stack<int>(); 
     List<string> listOfStrings = new List<string>(); 
     return stackOfInts; 
    } 

đây là những gì tôi đã cố gắng cho đến nay. tuy nhiên điều này không làm việc, tôi nhận được lỗi này:

Cannot implicitly convert type 'System.Collections.Generic.Stack<int>' to 'System.Collections.Generic.IEnumerable<T>'. An explicit conversion exists (are you missing a cast?) 

Tuy nhiên, nếu tôi thay thế IEnumerable<T> trong chữ ký phương pháp để IEnumerable<int>, tôi có thể trả lại bất kỳ bộ sưu tập các kiểu int. Điều này tuy nhiên có nghĩa là, bây giờ tôi không thể trả lại ListOfStrings nữa.

sẽ đánh giá cao bất cứ đề nghị hoặc ý tưởng :)

Trả lời

26

Bạn cần phải thêm một generic type parameter phương pháp của bạn:

public IEnumerable<T> ReturnSomething<T>() 
{ 
    Stack<T> stackOfT = new Stack<T>(); 
    return stackOfT; 
} 

Loại tham số xuất hiện sau tên phương pháp, nhưng trước khi các thông số. Cũng có thể có một phương thức có nhiều tham số kiểu.

Khi bạn gọi phương thức bạn có thể chỉ định các loại:

IEnumerable<int> myInts = ReturnSomething<int>(); 
+0

nhờ, công trình này thực sự, nhưng bây giờ tôi không thể dường như để thêm bất cứ điều gì để stack..stackOfInts.Push (3); nếu tôi thử điều này, nó nói: "trận đấu quá tải tốt nhất .. có một số đối số không hợp lệ". bất kỳ ý tưởng? – Thousand

+0

@JaneDoe: Bạn chỉ có thể thêm 'T' vào một 'Stack '. 3 không nhất thiết phải là 'T'. Trừ khi bạn thêm một [ràng buộc kiểu generic] (http://msdn.microsoft.com/en-us/library/d5x73970.aspx), bạn không biết một 'T' là gì, vì vậy bạn thậm chí không thể xây dựng một - để làm điều đó bạn cần một ràng buộc 'mới()'. Bạn đang cố gắng làm gì và tại sao bạn cần điều này? –

+1

tôi không cần điều này cho bất cứ điều gì đặc biệt, im chỉ cố gắng ra một loạt các điều. Nhưng tôi hiểu rồi, cảm ơn. – Thousand

10

Bí quyết là để tuyên bố<T> đúng, nếu bạn định nghĩa chung <T>, sau đó bạn phải dính vào nó trong các phương pháp của bạn, vì vậy nếu bạn có IEnumerable<T> thì ở nơi khác trong phương pháp của mình, bạn phải sử dụng <T> chứ không phải <int> hoặc bất kỳ loại nào khác.

Chỉ sau khi bạn thực sự sử dụng bạn loại chung bạn thay thế chung chung <T> cho loại thực.

Xem mẫu

class Foo<T> 
{ 
    public IEnumerable<T> GetList() 
    { 
     return new List<T>(); 
    } 

    public IEnumerable<T> GetStack() 
    { 
     return new Stack<T>(); 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Foo<int> foo = new Foo<int>(); 
     IEnumerable<int> list = foo.GetList(); 
     IEnumerable<int> stack = foo.GetStack(); 

     Foo<string> foo1 = new Foo<string>(); 
     IEnumerable<string> list1 = foo1.GetList(); 
     IEnumerable<string> stack1 = foo1.GetStack(); 
    } 
} 
1

Có bạn có thể trả lại bất kỳ loại nếu bạn thay đổi tôi Enumerable<T> to IEnumerable<dynamic>

như thế này:

public IEnumerable<dynamic> returnSomething() 
{ 
..... 
+2

lý do tại sao sử dụng generics ở tất cả nếu bạn đang đi để ném an toàn loại ra cửa sổ ... – Adam

+0

này thực sự có vẻ như một chút của một hack .. tôi đã thử nó và nó cũng không biên dịch. – Thousand

+0

@codesparkle Tôi đồng ý với quan điểm của bạn và theo dõi mạnh mẽ, nhưng chúng là lúc bạn không có quyền kiểm soát đối với phương thức API của bên thứ ba đã cho, vì vậy năng động là vị cứu tinh trong trường hợp như vậy – HatSoft

2
public IEnumerable<T> returnSomething() 
{ 
    Stack<int> stackOfInts = new Stack<int>(); 
    return (IEnumerable<T>) stackOfInts; 
} 
1

Tham số loại cần phải được xác định bởi người gọi ở đâu đó.

Hoặc khi instantiating một lớp chung:

public class MyClass<T> 
{ 
    public IEnumerable<T> returnSomething() 
    { 
     Stack<T> stackOfTs = new Stack<T>(); 
     List<T> listOfTs = new List<T>(); 
     return stackOfTs; 
    } 
} 

var v = new MyClass<int>(); 
foreach(var item in v.returnSomething()) 
{ 
} 

Hoặc khi gọi một phương pháp chung của một lớp không chung chung:

public class MyClass 
{ 
    public IEnumerable<T> returnSomething<T>() 
    { 
     Stack<T> stackOfTs = new Stack<T>(); 
     List<T> listOfTs = new List<T>(); 
     return stackOfTs; 
    } 
} 


var v = new MyClass(); 
foreach(var item in v.returnSomething<int>()) 
{ 
} 
Các vấn đề liên quan