2013-09-15 4 views
0

Я хотел написать метод расширения (для использования в текучем синтаксисе), так что если последовательность является:Должен ли я использовать доход при написании собственного расширения?

List< int> lst = new List< int>(){1,2,3 }; 

Я хочу повторить это 3 раза (к примеру). поэтому выход будет 123123123

я написал:

public static IEnumerable<TSource> MyRepeat<TSource>(this IEnumerable<TSource> source,int n) 
    { 
     return Enumerable.Repeat(source,n).SelectMany(f=>f); 
    } 

И теперь я могу это сделать:

lst.MyRepeat(3) 

выход:

enter image description here

Вопрос:

Должен ли я использовать Выход в методе расширения? Я пробовал yield return, но он здесь не работает. Почему это, и я должен использовать его.

редактировать

После ответа Муравьев я изменил его:

public static IEnumerable<TSource> MyRepeat<TSource>(this IEnumerable<TSource> source,int n) 
    { 
     var k=Enumerable.Repeat(source,n).SelectMany(f=>f); 

       foreach (var element in k) 
       { 
        yield return element; 
       } 
    } 

Но есть ли разница?

+0

Объясните, что означает «не работает». –

+0

@ant _Cannot неявно преобразовать тип 'System.Collections.Generic.IEnumerable ' в 'TSource'. Явное преобразование существует (вы пропускаете листинг?) _ –

+0

'yield return' используется только в низкоуровневой реализации, я думаю, что ваш код в порядке. –

ответ

3

Это происходит потому, что следующая уже возвращает IEnumerable:

Enumerable.Repeat(source,n).SelectMany(f=>f); 

При использовании yield ключевое слово, вы указываете, что данной итерации по методу будет возвращать то, что следует. Поэтому вы, по сути, говорите: «Каждая итерация даст IEnumerable<TSource>», когда на самом деле каждая итерация по методу, возвращающему IEnumerable<TSource>, должна давать TSource.

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

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

+0

Спасибо. см. мое редактирование. Есть ли разница? –

+0

Отредактировал свой ответ :) –

2

Ответ Ant P, конечно, правильный.

Вы использовали бы доход, если бы строили перечислимое, которое возвратилось самостоятельно, вместо того, чтобы полагаться на SelectMany.например:

public static IEnumerable<T> Repeat<T>(this IEnumberable<T> items, int repeat) 
{ 
    for (int i = 0; i < repeat; ++i) 
     foreach(T item in items) 
      yield return item; 
} 

Вещи вы уступаете является элементом последовательности. Код - это инструкции для создания последовательности исходных элементов.

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