2009-02-09 29 views
20

Tôi đang phát triển một ứng dụng mà ở đó tôi cần gọi một phương thức của một lớp chung và tôi không quan tâm đến các thể hiện kiểu thực tế. Một cái gì đó giống như mã Java sau đây:Tương đương với các ký tự đại diện Java trong C# generics

public class Item<T>{ 
    private T item; 

    public doSomething(){...} 
} 

... 
public void processItems(Item<?>[] items){ 
for(Item<?> item : items) 
    item.doSomething(); 
} 

Lúc đó, tôi đã giải quyết vấn đề bằng cách xác định giao diện với các phương thức tôi cần để gọi và thực hiện lớp chung.

public interface IItem 
{ 
    void doSomething(); 
} 

public class Item<T> : IItem { 
    private T item; 

    public void doSomething(){...} 
} 

... 
public void processItems(IItem[] items) 
{ 
foreach(IItem item in items) 
    item.doSomething(); 
} 

Cách giải quyết này hoạt động tốt, nhưng tôi muốn biết cách chính xác để đạt được hành vi tương tự.

EDIT:

tôi quên đề cập rằng người gọi của processItems không biết các loại thực tế. Trên thực tế, ý tưởng là mảng được chuyển làm đối số cho processItems có thể chứa các loại xen kẽ. Vì không thể có một mảng như vậy trong .Net, việc sử dụng một lớp cơ sở hoặc giao diện không chung chung có vẻ là cách duy nhất.

Trả lời

25

Cách thông thường để làm điều này sẽ được thực hiện phương pháp chung:

public void ProcessItems<T>(Item<T>[] items) { 
    foreach(Item<T> item in items) 
    item.DoSomething(); 
} 

Giả sử người gọi biết loại, loại suy luận nên có nghĩa là họ không cần phải xác định nó một cách rõ ràng. Ví dụ:

Item<int> items = new Item<int>(); // And then populate... 
processor.ProcessItems(items); 

Có nói rằng, việc tạo giao diện không chung chung chỉ định hoạt động độc lập kiểu cũng có thể hữu ích. Nó sẽ phụ thuộc rất nhiều vào trường hợp sử dụng chính xác của bạn.

+0

Blargh, một vài giây quá sớm. : P –

+0

Vâng, đánh bại tôi quá. Bạn có thể chỉnh sửa với ví dụ về người gọi không? –

+0

chỉ 'ProcessItems (dữ liệu); ' –

1

Không có cách nào bạn có thể bỏ qua các tham số loại trong .NET thực hiện chung; điều này là do thiết kế. Trong thực tế, điều này chỉ có thể đạt được trong Java vì triển khai dựa trên kiểu xóa của nó.

Bạn chỉ có thể sử dụng giao diện cơ bản không chung chung (nghĩ IEnumerable<T>IEnumerable).

0

Thêm vào bài đăng của Jon. làm cho phương thức chung (một mẫu) phủ nhận yêu cầu cho loại chức năng này (sử dụng <? >). Bạn luôn có thể đưa một loại vào một lớp/hàm chung và đối với các trường hợp bạn không biết loại nào bạn sẽ cần, bạn có thể tạo ra phương thức/lớp vi phạm chung chung ... cuối cùng người dùng phải cung cấp loại khi gọi một chức năng như vậy hoặc sử dụng một lớp chung chung, cho mã để có thể biên dịch ... nếu không bạn sẽ nhận được một số lỗi trình biên dịch.

3

Tôi thấy rằng bạn chỉ muốn gọi một số phương pháp không có tham số ... đã có hợp đồng cho điều đó: Action.

public void processItems(IEnumerable<Action> actions) 
{ 
    foreach(Action t in actions) 
    t(); 
} 

Chủ đầu tư:

List<Animal> zoo = GetZoo(); 
List<Action> thingsToDo = new List<Action>(); 
// 
thingsToDo.AddRange(zoo 
    .OfType<Elephant>() 
    .Select<Elephant, Action>(e => e.Trumpet)); 
thingsToDo.AddRange(zoo 
    .OfType<Lion>() 
    .Select<Lion, Action>(l => l.Roar)); 
thingsToDo.AddRange(zoo 
    .OfType<Monkey>() 
    .Select<Monkey, Action>(m => m.ThrowPoo)); 
// 
processItems(thingsToDo); 
0

Tôi đã đấu tranh với các vấn đề tương tự khi nó đến porting cụ từ Java, nơi tôi đã có cấu trúc như

if (o instanceof Collection<?>) doSoemthing((Collection<?>)o); 

May mắn thay nó quay ra rằng một ICollection chung cũng là một ICollection không chung chung và nếu ai đó cần phải xử lý các yếu tố trong nó như là đối tượng tinh khiết nó vẫn có thể:

if (o is ICollection) DoSomething((ICollection)o); 

Bằng cách đó, vì chúng tôi không quan tâm đến loại thực tế của các yếu tố trong bộ sưu tập, tất cả những gì chúng tôi nhận được ở đây là các đối tượng. Lưu ý ở đây: nếu bộ sưu tập đang giữ các loại nguyên thủy (ví dụ: int hoặc byte) thì các cú đánh tự động trong đó có thể giới thiệu hình phạt hiệu suất.

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