32

IEnumerable<T>を返す拡張メソッドを定義するにはどうすればよいIEnumerable<T>ですか? 目標は、拡張メソッドをすべてのIEnumerableユーザーが利用できるようにすることと、匿名型を使用できるIEnumerable<T>場所を作成することです。T

4

3 に答える 3

50

イテレータを記述する最も簡単な方法は、イテレータ ブロックを使用することです。次に例を示します。

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

上記は匿名型で問題なく使用できます。

もちろん、必要に応じて指定でき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);
}
于 2008-11-10T06:27:20.300 に答える
7
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;
            }
        }
    }
}
于 2008-11-10T06:32:32.643 に答える
0

この投稿は、開始するのに役立つ場合があります: How do you write a C# Extension Method for a Generically Typed Class . それがまさにあなたが探しているものかどうかはわかりませんが、始めるきっかけになるかもしれません。

于 2008-11-10T06:04:28.427 に答える