2009-02-09 2 views
20

Я разрабатываю приложение, в котором мне нужно вызвать метод универсального класса, и мне не нужен фактический тип экземпляра. Что-то вроде следующего кода Java:Что такое эквивалент шаблонов Java в C# generics

public class Item<T>{ 
    private T item; 

    public doSomething(){...} 
} 

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

В то время я был на спешке, так что я решил мою проблему, определив интерфейс с методами мне нужно, чтобы вызвать и сделал общий класс реализации.

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(); 
} 

Этот способ прекрасно работает, но я хотел бы знать, что это правильный путь для достижения такого же поведения.

EDIT:

Я забыл передать, что вызывающий processItems не знает реальных типов. На самом деле идея заключалась в том, что массив, переданный как аргумент processItems, может содержать смешанные типы. Так как его невозможно получить в .Net, использование не общего базового класса или интерфейса кажется единственным способом.

ответ

25

Обычный способ сделать это было бы сделать метод родовым:

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

Предполагая вызывающей знает тип вывод типа должен означать, что они не должны явно указывать. Например:

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

Сказав, что, создавая не-универсальный интерфейс, определяющий операции типа агностик может быть полезным. Это будет сильно зависеть от вашего конкретного варианта использования.

+0

Blargh, через несколько секунд. : P –

+0

Да, избили меня тоже. Можете ли вы редактировать с помощью примера вызывающего? –

+0

просто 'ProcessItems (data);' –

1

Невозможно опустить параметры типа в универсальной реализации .NET; это по дизайну. Фактически, это может быть достигнуто только на Java из-за его реализации на основе стирания.

Вы можете использовать базовый не общий интерфейс (думаю, IEnumerable<T> и IEnumerable).

0

В дополнение к сообщению Джона. создание метода generic (шаблон) отменяет требование для такого рода функциональных возможностей (с использованием <? >). Вы всегда можете подавать тип в общий класс/функцию, и в тех случаях, когда вы не знаете, какой тип вам понадобится, вы также можете сделать способ нарушения/универсальный класс ... в конечном итоге пользователь должен указать тип при вызове такую ​​функцию или использование общего класса, чтобы код мог компилироваться ... в противном случае вы получите некоторые ошибки компилятора.

3

Я вижу, что вы только хотите вызвать какой-либо метод без параметров ... для этого уже есть контракт: Action.

public void processItems(IEnumerable<Action> actions) 
{ 
    foreach(Action t in actions) 
    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

Я боролся с той же проблемой, когда дело дошло до портирования вещи из Java, где я имел конструкции, как

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

К счастью получается что общий ICollection также является не общим ICollection, и если кому-то нужно обрабатывать элементы в нем как чистые объекты, это все еще возможно:

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

Таким образом, поскольку мы не заботимся о фактическом типе элементов в коллекции, все, что мы получаем здесь, это объекты. Примечание: если коллекция хранит примитивные типы (например, int или byte), то автобоксинг-ногами, в результате чего может возникнуть штраф за производительность.

Смежные вопросы