Определить метод расширения для IEnumerable <T>, который возвращает IEnumerable <T>?

голоса
20

Как определить метод расширения для IEnumerable<T>возвращающий IEnumerable<T>? Цель состоит в том, чтобы сделать метод расширения для всех IEnumerableи IEnumerable<T>где Tможет быть анонимным типом.

Задан 10/11/2008 в 06:53
источник пользователем
На других языках...                            


3 ответов

голоса
36

Самый простой способ, чтобы написать любой итератор с блоком итератора, например:

static IEnumerable<T> Where<T>(this IEnumerable<T> data, Func<T, bool> predicate)
{
    foreach(T value in data)
    {
        if(predicate(value)) yield return value;
    }
}

Ключевым моментом здесь является « yield return», которая превращает метод в блок итератора, с компилятором генерирующего нумератор ( IEnumerator<T>) , который делает то же самое. При вызове логического вывода общего типа обрабатывает Tавтоматически, так что вам просто необходимо:

int[] data = {1,2,3,4,5};
var odd = data.Where(i=>i%2 != 0);

Выше, можно использовать с анонимными типами просто отлично.

Можно, Coure, укажите , Tесли вы хотите ( до тех пор , как это не анонимно):

var odd = data.Where<int>(i=>i%2 != 0);

Re IEnumerable(не общий), ну, самый простой подход к абоненту использовать .Cast<T>(...)или .OfType<T>(...)получить IEnumerable<T>первый. Вы можете передать this IEnumerableв выше, но вызывающий абонент должен будет указать Tсебя, вместо того , чтобы компилятор умозаключений. Вы не можете использовать это с Tбудучи анонимным типом, поэтому мораль здесь: не использовать необщую форму IEnumerableанонимными типов.

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


(Обновлено)

После обсуждения, вот способ использовать Cast<T>с анонимными типами. Ключ должен предоставить аргумент , который может быть использован для вывода типа (даже если аргумент никогда не используется). Например:

static void Main()
{
    IEnumerable data = new[] { new { Foo = "abc" }, new { Foo = "def" }, new { Foo = "ghi" } };
    var typed = data.Cast(() => new { Foo = "never used" });
    foreach (var item in typed)
    {
        Console.WriteLine(item.Foo);
    }
}

// note that the template is not used, and we never need to pass one in...
public static IEnumerable<T> Cast<T>(this IEnumerable source, Func<T> template)
{
    return Enumerable.Cast<T>(source);
}
Ответил 10/11/2008 в 07:27
источник пользователем

голоса
3
using System;
using System.Collections.Generic;

namespace ExtentionTest {
    class Program {
        static void Main(string[] args) {

            List<int> BigList = new List<int>() { 1,2,3,4,5,11,12,13,14,15};
            IEnumerable<int> Smalllist = BigList.MyMethod();
            foreach (int v in Smalllist) {
                Console.WriteLine(v);
            }
        }

    }

    static class EnumExtentions {
        public static IEnumerable<T> MyMethod<T>(this IEnumerable<T> Container) {
            int Count = 1;
            foreach (T Element in Container) {
                if ((Count++ % 2) == 0)
                    yield return Element;
            }
        }
    }
}
Ответил 10/11/2008 в 07:32
источник пользователем

голоса
0

Это сообщение может помочь вам начать работу: Как вы пишете C # метод расширения для обобщенно типизированного класса . Я не уверен , если это именно то , что вы ищете , но это может вам начать.

Ответил 10/11/2008 в 07:04
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more