C# - .NET 4.x Расширение интерфейса

Рейтинг: 4Ответов: 2Опубликовано: 26.04.2015

Как возможно расширить интерфейc IEnumerable ? Надо что бы метод возвращал каждый второй элемент таблицы. Желательно с примерами =) Спасибо заранее.

Ответы

▲ 6Принят

Я бы предложил сделать так:

  • Написать метод для IEnumerable<T>, а не просто для IEnumerable. Тогда можно будет получать типизированный результат.
  • Решить общую задачу: получение каждого n-го элемента. Это будет универсальное решение, которое легко использовать для получения каждого 2-го элемента.

Код:

public static class EnumerableExtensions
{
    public static IEnumerable<T> GetEveryNth<T>(this IEnumerable<T> source, int n)
    {
        if (n <= 0)
            throw new ArgumentOutOfRangeException("n");
        int index = 1;
        foreach (var element in source)
        {
            if (index % n == 0)
                yield return element;
            index++;
        }
    }

    public static IEnumerable<T> GetEverySecond<T>(this IEnumerable<T> source)
    {
        return source.GetEveryNth(2);
    }
}

Демонстрация:

private static void Main()
{
    var a = Enumerable.Range(1, 6).ToArray(); // 1 2 3 4 5 6
    // Получаем каждый второй элемент
    foreach (var x in a.GetEverySecond())
        Console.Write(x + " "); // 2 4 6
    Console.WriteLine();
    // Получаем каждый третий элемент
    foreach (var x in a.GetEveryNth(3))
        Console.Write(x + " "); // 3 6
}
▲ 7

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

Выглядят методы расширения как статические методы в статическом классе, при этом принимающие в качестве первого параметра экземпляр "расширяемого" класса или интерфейса с модификатором this. Например так:

public static class EnumerableExtension 
{
    public static IEnumerable EverySecond(this IEnumerable en)
    { 
         // некая логика
    }
}

Если это учебное задание, то скорее всего препод будет рад, если вы напишете и реализуете интерфейс, наследующийся от IEnumerable и определите таковой метод в нем. Что-то такое:

public interface IEnumerableExt : IEnumerable
{
    IEnumerable EverySecond();        
}


public class EnumerableExt  : IEnumerableExt 
{
    public IEnumerable EverySecond()
    { 
         // некая логика
    }    
}