List <T>とIEnumerable <T>の間で自由に変換


103

どのようにしてa List<MyObject>をan に変換し、IEnumerable<MyObject>再び戻すことができますか?

リストで一連のLINQステートメントを実行するために、これを行います。たとえば、 Sort()


これは、この質問に覆われているstackoverflow.com/questions/31708/...
ジョン

回答:


148
List<string> myList = new List<string>();
IEnumerable<string> myEnumerable = myList;
List<string> listAgain = myEnumerable.ToList();

30
ただし、myEnumarableはmyListと同じオブジェクトインスタンスですが、listAgainはmyEnumerableと同じオブジェクトインスタンスではないことに注意してください。何をしたいか、そしてmyEnumerableが何であるかによって、「List <string> listAgain = myEnumerable as List <string>;」良いかもしれません。
ChrisW、2009年

1
Chrisw:はい、もちろんそうですが、IEnumerable <T>インターフェイスは不変であるため、その方向で問題が発生することはなく、型の安全性を処理する関数がある場合、キャストバックは汚れているように感じます。
Tamas Czinege 2009年

1
元のmyListオブジェクトを使用することもできます。(私は本当に質問をしないと思います)
sth

6
それは、彼がmyListを編集する場合、myEnumrableを編集するということですが、listAgainを編集する場合、myEnumerableを編集しないことになります。
ChrisW、2009年

15
忘れないでくださいusing System.Linq;、そうしないとToList()ができなくなります
Jason

21

A List<T>IEnumerable<T>なので、実際にはa List<T>をに「変換」する必要はありませんIEnumerable<T>。a List<T>IEnumerable<T>なので、List<T>型の変数にa を割り当てるだけIEnumerable<T>です。

逆に言えば、すべてIEnumerable<T>List<T>必須ではないので、のToList()メンバーメソッドを呼び出す必要がありますIEnumerable<T>


4
技術的には、ToListはSystem.Linq.Enumerableのメンバーメソッドです
Amy B

2
Davidがそうだと言っているように、IEnumerableをListにキャストできると思います。
abatishchev

9

A List<T>は既になIEnumerable<T>ので、List<T>変数に対して直接LINQステートメントを実行できます。

LINQ拡張メソッドが表示されない場合は、ソースファイルにディレクティブOrderBy()がないためだと思いusing System.Linqます。

List<T>ただし、LINQ式の結果を明示的に変換して戻す必要があります。

List<Customer> list = ...
list = list.OrderBy(customer => customer.Name).ToList()

「OrderBy()などのLINQ拡張メソッドが表示されない場合」これが私の問題でした。ありがとうございました。
RyPope 2014年

5

余談:標準のLINQ演算子(前の例のように)は既存のリストを変更しないことに注意してください- list.OrderBy(...).ToList()並べ替えられたシーケンスに基づいて新しいリストを作成します。ただし、ラムダをList<T>.Sort次のように使用できるようにする拡張メソッドを作成するのは非常に簡単です。

static void Sort<TSource, TValue>(this List<TSource> list,
    Func<TSource, TValue> selector)
{
    var comparer = Comparer<TValue>.Default;
    list.Sort((x,y) => comparer.Compare(selector(x), selector(y)));
}

static void SortDescending<TSource, TValue>(this List<TSource> list,
    Func<TSource, TValue> selector)
{
    var comparer = Comparer<TValue>.Default;
    list.Sort((x,y) => comparer.Compare(selector(y), selector(x)));
}

それからあなたは使うことができます:

list.Sort(x=>x.SomeProp); // etc

これにより、通常と同じ方法で既存のリストが更新されますList<T>.Sort


このステートメントに対する若干の修正:標準のLINQ演算子は既存のリストを変更しません。代わりに、作業を行うために必要なロジックを含む新しいIEnumerableを作成します。ただし、このロジックは、IEnumeratorが要求されるまで実際には実行されません。
Vojislav Stojkovic

@Vojislav-前の例で終わるという意味で意味がありましたToList-明確にしますが。
Marc Gravell

1

に変換List<T>していますIEnumerable<T>

List<T>実装IEnumerable<T>(および他の多くのようにIList<T>, ICollection<T>)ので、それ以来、既にIEnumerableをするために、リスト背中を変換する必要はありませんIEnumerable<T>

例:

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
}

Person person1 = new Person() { Id = 1, Name = "Person 1" };
Person person2 = new Person() { Id = 2, Name = "Person 2" };
Person person3 = new Person() { Id = 3, Name = "Person 3" };

List<Person> people = new List<Person>() { person1, person2, person3 };

//Converting to an IEnumerable
IEnumerable<Person> IEnumerableList = people;

Enumerable.AsEnumerable()メソッドも使用できます

IEnumerable<Person> iPersonList = people.AsEnumerable();

に変換IEnumerable<T>していますList<T>

IEnumerable<Person> OriginallyIEnumerable = new List<Person>() { person1, person2 };
List<Person> convertToList = OriginallyIEnumerable.ToList();

これはEntity Frameworkで役立ちます


0

記憶の重複を防ぐために、resharperはこれを示唆しています:

List<string> myList = new List<string>();
IEnumerable<string> myEnumerable = myList;
List<string> listAgain = myList as List<string>() ?? myEnumerable.ToList();

.ToList()は新しい不変リストを返します。したがって、listAgainを変更しても、@ Tamas Czinegeの回答のmyListには影響しません。これは、少なくとも2つの理由でほとんどの場合において正しいです。これは、一方の領域での変更が他方の領域に影響するのを防ぐのに役立ち(疎結合)、コンパイラの問題でコードを設計するべきではないため、非常に読みやすくなっています。

ただし、タイトループにある場合や、組み込みシステムやメモリ不足のシステムで作業している場合など、コンパイラの考慮事項を考慮する必要がある特定のインスタンスがあります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.