2010-04-23 32 views
10

Tôi đang cố gắng để lưu trữ một danh sách các đối tượng chung trong một danh sách chung chung, nhưng tôi đang gặp khó khăn khi khai báo nó. Đối tượng của tôi trông giống như:Một danh sách chung của generics

public class Field<T> 
{ 
    public string Name { get; set; } 
    public string Description { get; set; } 
    public T Value { get; set; } 

    /* 
    ... 
    */ 
} 

Tôi muốn tạo danh sách các mục này. Vấn đề của tôi là mỗi đối tượng trong danh sách có thể có một loại riêng biệt, để danh sách dân cư có thể chứa một cái gì đó như thế này:

{ Field<DateTime>, Field<int>, Field<double>, Field<DateTime> } 

Vậy làm cách nào để khai báo?

List<Field<?>> 

(Tôi muốn ở mức an toàn nhất có thể, vì vậy tôi không muốn sử dụng ArrayList).

+0

Đó là một ý tưởng thú vị để "ở mức an toàn nhất có thể", tuy nhiên, bạn có vi phạm khái niệm http://en.wikipedia.org/wiki/YAGNI không? Hãy suy nghĩ về cách bạn sẽ truy cập danh sách đó, bạn có thực sự cần nó cụ thể không? –

Trả lời

21

Đây là tình huống mà nó có thể lợi ích bạn có một lớp trừu tượng cơ sở (hoặc giao diện) có chứa các bit không chung chung:

public abstract class Field 
{ 
    public string Name { get; set; } 
    public string Description { get; set; } 
} 

public class Field<T> : Field 
{  
    public T Value { get; set; } 

    /* 
    ... 
    */ 
} 

Sau đó, bạn có thể có một List<Field>. Điều đó thể hiện tất cả thông tin bạn thực sự biết về danh sách. Bạn không biết các loại giá trị của các trường, vì chúng có thể thay đổi từ một trường này sang trường khác.

+0

@Jon - Lớp học đầu tiên có phải là một lớp chung hay chỉ là một lớp đơn giản? – Giorgi

+1

@Giorgi, 'lớp trừu tượng Field ' trông giống như lỗi đánh máy. Tôi đã tự do điều chỉnh nó. –

+0

Ông vẫn phải đúc để có được loại giá trị thực tế ... nhưng đây là giải pháp duy nhất mà tôi có thể nghĩ đến quá, mà không có một loại "tuple" thực tế. – tames

5

Có thể triển khai giao diện.

interface IField 
{ 
} 

class Field<T> : IField 
{ 
} 

...

List<IField> fields = new List<IField>() { new Field<int>(), new Field<double>() }; 
+0

Điều này khiến anh ta ở cùng vị trí vì IField sẽ không chứa loại (T). khác với chỉ sử dụng 'đối tượng' bởi vì anh ta vẫn phải đúc để lấy giá trị – tames

+0

@tames, anh ta ở vị trí tốt hơn vì các phần tử trong danh sách của anh ta phải triển khai IField (hoặc kế thừa từ Field, trong ví dụ của Jon). danh sách vẫn còn được đánh máy mạnh hơn một danh sách các đối tượng –

+0

@anthony ...Tôi đồng ý và tôi đã sử dụng cả giải pháp lớp giao diện và lớp cơ sở. – tames

5

Bạn không thể khai báo một danh sách các loại generic mà không biết loại generic tại thời gian biên dịch.

Bạn có thể khai báo một List<Field<int>> hoặc một List<Field<double>>, nhưng không có loại cơ sở phổ biến khác cho Field<int>Field<double> hơn object. Vì vậy, chỉ List<T> có thể chứa các loại trường khác nhau sẽ là List<object>.

Nếu bạn muốn một loại cụ thể hơn cho danh sách, bạn sẽ phải làm cho lớp Field<T> kế thừa một lớp hoặc triển khai giao diện. Sau đó, bạn có thể sử dụng nó cho loại chung trong danh sách.

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