List <T>와 IEnumerable <T>간에 자유롭게 변환


103

a List<MyObject>를 로 변환 한 IEnumerable<MyObject>다음 다시 되돌리려면 어떻게해야합니까?

목록에서 일련의 LINQ 문을 실행하기 위해이 작업을 수행하고 싶습니다. Sort()


John

답변:


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

1
Chrisw : 네, 물론 맞습니다. 그러나 IEnumerable <T> 인터페이스는 불변이므로 그 방향으로 문제를 일으키지 않으며 형식 안전성을 처리 할 함수가있을 때 다시 캐스팅하는 것이 더러워 집니다 .
Tamas Czinege

1
원래 myList 객체를 사용할 수도 있습니다. (정말 질문을받지 못하는 것 같아요)
sth

6
그가 myList를 편집하면 myEnumrable을 편집하고 listAgain을 편집하면 myEnumerable을 편집하지 않을 것입니다.
ChrisW

15
잊지 마세요 using System.Linq;또는 당신이 ToList () 할 수 없습니다
제이슨

21

A List<T>IEnumerable<T>이므로 실제로 a List<T>를 .txt로 '변환'할 필요가 없습니다 IEnumerable<T>. a List<T>는 이므로 IEnumerable<T>단순히 List<T>유형의 변수에 a 를 할당 할 수 있습니다 IEnumerable<T>.

반대로 모든 IEnumerable<T>것이 List<T>오프 코스가 아니므로 .NET Framework의 ToList()멤버 메서드 를 호출해야 합니다 IEnumerable<T>.


4
기술적으로, ToList은 System.Linq.Enumerable의 멤버 방법은
에이미 B

2
David가 말한 것처럼 목록에서 IEnumerable을 캐스팅 할 수 있다고 생각합니다.
abatishchev

9

A List<T>는 이미 IEnumerable<T>이므로 List<T>변수에서 직접 LINQ 문을 실행할 수 있습니다 .

LINQ 확장 메서드 OrderBy()가 보이지 않으면 using System.Linq소스 파일에 지시문 이 없기 때문이라고 생각 합니다.

하지만 LINQ 식 결과를 다시 List<T>명시 적으로 다시 변환해야합니다 .

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>)하므로 List를 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에 영향을 미치지 않습니다. 이것은 적어도 두 가지 이유로 대부분의 경우에 정확합니다. 이것은 한 영역의 변경이 다른 영역에 영향을 미치는 (느슨한 결합)을 방지하는 데 도움이되며 컴파일러 문제로 코드를 설계해서는 안되므로 매우 읽기 쉽습니다.

그러나 타이트한 루프에 있거나 임베디드 또는 메모리 부족 시스템에서 작업하는 것과 같은 특정 인스턴스가 있으며 컴파일러 고려 사항을 고려해야합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.