5

私はC# AsEnumerableを読んでいます:

「IEnumerable インターフェイスはジェネリック インターフェイスです。これは、型がループ用に実装できるテンプレートを定義することを意味します。ジェネリック メソッドである AsEnumerable メソッドを使用すると、特定の型を同等の IEnumerable にキャストできます」

さらに、コード例:

using System;
using System.Linq;

class Program
{
   static void Main()
   {
       // Create an array type.
        int[] array = new int[2];
        array[0] = 5;
        array[1] = 6;
        // Call AsEnumerable method.
        var query = array.AsEnumerable();
        foreach (var element in query)
        {
            Console.WriteLine(element);
        }
    }
}

ループを使用するには、配列をIEnumerable型オブジェクトに変換する必要があるようです ( foreach ?)。

しかし、foreachを配列に直接適用すると、まったく同じ結果が得られます。

using System;
//using System.Linq;

class Program
{
    static void Main()
    {
        // Create an array type.
        int[] array = new int[2];
        array[0] = 5;
        array[1] = 6;
        // Call AsEnumerable method.
        //var query = array.AsEnumerable();
        foreach (var element in array)
        {
            Console.WriteLine(element);
        }
    }
}

したがって、AsEnumerable()メソッドの説明を含む Web ページ全体は無効です。
私は何を取りこぼしたか?

4

4 に答える 4

4

例えが悪くて気持ち悪いはずです。これは、やや不自然な例ですが、より良い例です。

たとえば、次のように、配列型で定義された拡張メソッドがあるとします。

public static class ArrayExtension {

    public static bool Any<T>(this T[] source, Func<T,bool> predicate)
    {
       Console.WriteLine("Undesirable side behaviour");
       SomeResourceIntensiveOperation();

       Console.WriteLine("Inefficient implementation");
       return source.Where(predicate).Count() != 0;
    }

}

そして私はそうします

int[] nums = new []{1,2,3,4,5};
nums.Any(n=> n % 2 == 0);

実装が必要ない場合でも、実装を実行して実行します。することで

nums.AsEnumerable().Any(n => n % 2 == 0);

デフォルトの実装が呼び出されます。

本当の利点は、IQueryable実装 (LINQ-to-SQL など) を使用している場合です。たとえば、Wherefor IEnumerableは次のように定義されているためです。

public static IEnumerable<TSource> Where<TSource>(
this IEnumerable<TSource> source,
Func<TSource, bool> predicate) 

しかし、IQueryable.Whereはで定義されています

public static IQueryable<TSource> Where<TSource>(
this IQueryable<TSource> source,
Expression<Func<TSource, bool>> predicate)

IQueryable の動作が望ましくない場合は、 を呼び出しAsEnumerable()て IEnumerable の動作を強制できます。

于 2013-01-05T12:33:31.650 に答える
2

MSDNから

( ) メソッドはAsEnumerable<TSource>、ソースのコンパイル時の型をそれ自体に実装するIEnumerable<TSource>型から変更する以外に効果はありません。IEnumerable<T>IEnumerable<T>

AsEnumerable<TSource>( IEnumerable<TSource>) は、シーケンスが実装されている場合にクエリの実装を選択するために使用できますが、IEnumerable<T>使用可能なパブリック クエリ メソッドのセットも異なります。たとえば、 、、などIEnumerable<T>の独自のメソッドを実装して持つジェネリック クラス Table がある場合、を呼び出すと、Table の publicメソッドが呼び出されます。データベース テーブルを表す Table 型には、述語引数を式ツリーとして取り、そのツリーをリモート実行用の SQL に変換する Where メソッドを含めることができます。述語がローカル メソッドを呼び出すなどの理由で、リモート実行が望ましくない場合は、そのメソッドを使用してカスタム メソッドを非表示にし、代わりに標準のクエリ演算子を使用できるようにすることができます。WhereSelectSelectManyWhereWhereAsEnumerable<TSource>

于 2013-01-05T12:01:26.097 に答える
1

あなたの例では論理的に(つまり配列から)意味がありません。私は、最初のコードが初心者、またはもっと下の例によって書かれたと思います。

「AsEnumerable」がクエリの評価をトリガーし、ORMに応じてトリガーされるため、LINQの意味では意味があります。これは、ループ内で再利用するためにデータベース接続を解放することを意味します。

それは言った:

あなたは例を読みすぎています。例では、コードは「良い」ものではなく、要点を示すためのものです。この場合、AsEnumerableの使用をデモンストレーションすることは理にかなっているかもしれません-そして、配列は、例を短くするために、初期化する(コードの行に関して)最も速い列挙可能なオブジェクトです。例は特定のことを指摘していますが、それらは何にとっても「良いコード」ではありません。

于 2013-01-05T11:56:56.773 に答える
0

これは単なる別の例です。このメソッドがあるとします:

static void MyMeth(int[] numbers)
{
  var query = numbers.Reverse();  // works fine, calls Linq extension

  // ... use query ...
}

次に、代わりnumbersに aに変更して、次のことを試してみることにしました。List<int>

static void MyMeth(List<int> numbers)
{
  var query = numbers.Reverse();  // will not compile!

  // ... use query ...
}

ここでの問題は、List<>クラスにと呼ばれる別のメソッドがあることですReverse。そのメソッドは戻ります(元のインプレースをvoid変更するため)。List<>私はそれをしたくありません。1 つの解決策は、numbers明示的にアップキャストすることです。

static void MyMeth(List<int> numbers)
{
  var query = ((IEnumerable<int>)numbers).Reverse();  // fine; Linq

  // ... use query ...
}

しかし、別の解決策は次のAsEnumerable<>とおりです。

static void MyMeth(List<int> numbers)
{
  var query = numbers.AsEnumerable().Reverse();  // fine too; Linq

  // ... use query ...
}

結論: methodの目的はAsEnumerable、汎用型の拡張メソッドをたまたま「隠す」特殊な型のメソッドを「忘れる」ことIEnumerable<>です。これは、「特殊化された」型IQueryable<>が (拡張) メソッドが存在する/継承する場合などWhereSelect何か異なることを行う (つまり、ラムダを式ツリーとして取り込み、分析し、「変換」する) 場合に非常に重要になる可能性があります。 SQL または何かに) doWhereなどSelectよりもIEnumerable<>

于 2014-01-29T13:42:18.090 に答える