2015-04-08 5 views
1

У меня есть функция со следующей подписью:Passing производный тип в выводимый параметр

IEnumerable<TypeA> GetItems(string s, out IEnumerable<TypeB> otherItems) 

(Для записи, TypeA и TypeB не связаны между собой типы, мой вопрос не вовлекает их, кроме как заполнители).

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

Рассмотрим:

private List<TypeA> _fieldA; 
private List<TypeB> _fieldB; 

// ... other code 

// conversion errors for _fieldA and _fieldB: 
_fieldA = Fns.GetItems(str, out _fieldB); 

// _fieldA is now ok, but not _fieldB: 
_fieldA = Fns.GetItems(str, out _fieldB).ToList(); 

// Same result as previous, out param must be a variable. 
_fieldA = Fns.GetItems(str, out _fieldB.AsEnumerable()).ToList(); 

// This works but makes me sad: 
IEnumerable<TypeB> tempEnumerable; 
_fieldA = Fns.GetItems(str, out tempEnumerable).ToList(); 
_fieldB = tempEnumerable.ToList(); 

В принципе, это то, что четвертая попытка лучший способ получить то, что мне нужно, или там «лучше» способ получить списки из этой функции (короткие модификации функции, что невозможно)?

+0

Вы имеете в виду 4-ю попытку? Если да, да, это все, что есть. Вы не можете передать поле непосредственно в метод, так как это неправильный тип. Аргументы параметра 'out' и' ref' должны быть точно того же типа, что и параметр. –

+0

Есть ли причина, по которой вы не можете определить '_fieldA' и' _fieldB' как 'IEnumerable <>' вместо 'List <>'? – juharr

+0

Er, четвертый да. Я довольно хорошо рассчитываю на двоих, все еще работаю над остальными. – helrich

ответ

2

Поскольку вы не можете изменить подпись функция, создайте функцию-обертку для него: (Будет ли это еще одна перегрузка этого метода, или метода в другой класс, если это будет необходимо.)

//TODO come up with a better name 
List<TypeA> GetItemsAsLists(string s, out List<TypeB> otherItems) 
{ 
    IEnumerable<TypeB> tempEnumerable; 
    var output = Fns.GetItems(s, out tempEnumerable).ToList(); 
    otherItems = tempEnumerable.ToList(); 
    return output.ToList(); 
} 

В какой-то момент , где-то у вас должна быть переменная типа IEnumerable<TypeB> для вызова этого метода. Вы можете скрыть это (как в приведенном выше случае), но в какой-то момент он должен будет существовать.

+0

Хорошо, у меня было подозрение, что это так, но не был уверен, что есть какой-то метод расширения ниши или другой способ, который немного поутихнул бы. – helrich

+0

@helrich В подобных ситуациях почему-то избегать использования 'out' /' ref'. Вы обнаружите, что хорошие API не будут использовать его вообще. – Servy

+0

Я могу видеть, откуда они пришли с этим решением, обе последовательности зависят друг от друга и вычисляются друг от друга, так почему бы не вернуть их обоих в один и тот же вызов? Я бы предпочел «Tuple» над этим, хотя! – helrich