IEnumerable <T>에서 ICollection <T>로 변환 할 수 없습니다.


91

다음을 정의했습니다.

public ICollection<Item> Items { get; set; }

이 코드를 실행할 때 :

Items = _item.Get("001");

다음과 같은 메시지가 나타납니다.

Error   3   
Cannot implicitly convert type 
'System.Collections.Generic.IEnumerable<Storage.Models.Item>' to 
'System.Collections.Generic.ICollection<Storage.Models.Item>'. 
An explicit conversion exists (are you missing a cast?)

누군가 내가 뭘 잘못하고 있는지 설명 할 수 있습니까? Enumerable, Collections 및 ToList () 사용의 차이점에 대해 매우 혼란 스럽습니다.

추가 된 정보

나중에 내 코드에 다음이 있습니다.

for (var index = 0; index < Items.Count(); index++) 

Items를 IEnumerable로 정의해도됩니까?


3
_item 유형과 Get (string) 서명 (특히 반환 유형)에 대한 자세한 정보를 제공 할 수 있습니까?
Dr. Andrew Burnett-Thompson

이렇게 유형을 바꾸지 않겠습니까? public IEnumerable<Item> Items { get; set; }특별한 이유가 ICollection있습니까?
Shadow Wizard is Ear For You

IEnumerable <T> Get (문자열 pk);
Samantha JT Star

답변:


113

ICollection<T>IEnumerable<T>그래서에서 상속 하여 결과를 할당합니다.

IEnumerable<T> Get(string pk)

ICollection<T>두 가지 방법이있다.

// 1. You know that the referenced object implements `ICollection<T>`,
//    so you can use a cast
ICollection<T> c = (ICollection<T>)Get("pk");

// 2. The returned object can be any `IEnumerable<T>`, so you need to 
//    enumerate it and put it into something implementing `ICollection<T>`. 
//    The easiest is to use `ToList()`:
ICollection<T> c = Get("pk").ToList();

두 번째 옵션은 더 유연하지만 성능에 훨씬 더 큰 영향을 미칩니다. 또 다른 옵션은 인터페이스에서 IEnumerable<T>추가 된 추가 기능이 필요하지 않은 경우 결과를로 저장하는 것 ICollection<T>입니다.

추가 성능 설명

당신이 가지고있는 루프

for (var index = 0; index < Items.Count(); index++)

작동 IEnumerable<T>하지만 비효율적입니다. 에 대한 각 호출 Count()에는 모든 요소 의 완전한 열거 가 필요합니다 . 컬렉션 및 Count속성 (괄호 제외)을 사용하거나 foreach 루프로 변환합니다.

foreach(var item in Items)

1
ICollection에서 추가 된 추가 기능은 무엇입니까?
Samantha JT Star

7
ICollection<T>조작 할 수 있지만 (자세한 내용은 문서 참조)는 IEnumerable<T>열거 형 만 가능합니다.
Anders Abel

다른 LINQ 쿼리를 실행할 수있는 무언가가 필요합니다. 목록에 추가하거나 이와 같은 작업을 수행 할 필요가 없습니다. 그것은 내가 ICollection을 사용하는 것이 더 나을 것이라는 것을 의미합니까?
Samantha JT Star

LINQ는에서 작동 IEnumerable<T>하므로 IEnumerable<T>이 경우에 충분하다.
Anders Abel

31

당신은 직접 변환 할 수 없습니다 IEnumerable<T>ICollection<T>. 의 ToList방법을 사용 IEnumerable<T>하여 변환 할 수 있습니다.ICollection<T>

someICollection = SomeIEnumerable.ToList();


이것은 나를 위해 작동합니다. 그러나 변환하는 것이 좋은 생각입니까, 아니면 항목의 유형으로 IEnumerable을 사용하는 것이 더 낫습니다. IEnumerable을 사용하면 나중에 필요한 경우 프로그램에서 항목에 대해 더 많은 작업을 수행 할 수 있도록 만들고 있습니까?
Samantha JT Star

ICollection은 이미 IEnumerable을 구현합니다. 사용 가능한 작업이 염려된다면 ICollection으로 가야한다고 생각합니다. 당신은 둘 사이의 실제 차이를 읽은 다음 사용하려는 실제로 결정할 수 있다면 더 좋다
하리스 하산

ToList ()를 사용하면 어떤 이점이 있는지 이해하려고합니다. 데이터가 있으면 Items에 대해 LINQ 쿼리를 실행하고 싶습니다.
Samantha JT Star

ToList ()는 작동하지만 주석에서 언급했듯이 Get ()은 ICollection을 반환하므로 실제로 ICollection <T>로 캐스트하거나 더 나은 방법으로 Get의 반환 서명을 ICollection <T>로 변경하면됩니다. . / 복사 ToList을 사용하거나 ToArray가 작동하지만 그것은 또한 불필요한 만들 메모리가 부과됩니다 작동
닥터 앤드류 버넷 - 톰슨

IEnumerable 및 ICollection 모두에 대해 LINQ 쿼리를 실행할 수 있습니다. 장점 .. 내가 지금 아는 한 가지는 Count ICollection이 개수를 유지하고 IEnumerable이 얼마나 많은 항목을 가지고 있는지 계산하여 결과를 반환한다는 것입니다. ICollection이는 Ienumerables하지 않는 추가 제거 방법을 제공
하리스 하산

1

질문에 대한 추가 정보 보류 중 :

항목 유형 및 Get의 서명에 대한 자세한 정보를 제공하십시오.

시도 할 수있는 두 가지 방법은 다음과 같습니다.

  • _item.Get의 반환 값을 (ICollection)으로 캐스팅하려면
  • 두 번째로 _item.Get ( "001"). ToArray () 또는 _item.Get ( "001"). ToList ()를 사용합니다.

두 번째는 어레이 복사본에 대한 성능 저하가 발생합니다. Get의 서명 (반환 유형)이 ICollection이 아니면 첫 번째가 작동하지 않고 IEnumerable이 아니면 두 번째가 작동하지 않습니다.


질문과 의견에 대한 설명에 따라 _item.Get ( "001") 반환 유형을 ICollection에 개인적으로 선언합니다. 즉, 불필요한 생성 / 복사 작업을 수반하는 캐스팅이나 변환 (ToList / ToArray를 통해)을 수행 할 필요가 없습니다.

// Leave this the same
public ICollection<Item> Items { get; set; }

// Change function signature here:
// As you mention Item uses the same underlying type, just return an ICollection<T>
public ICollection<Item> Get(string value); 

// Ideally here you want to call .Count on the collectoin, not .Count() on 
// IEnumerable, as this will result in a new Enumerator being created 
// per loop iteration
for (var index = 0; index < Items.Count(); index++) 

친애하는,


1
서명은 다음과 같습니다. IEnumerable <T> Get (string pk); 항목은 반환되는 항목 레코드를 보관하는 데 사용됩니다. 나중에 보고서를 작성하기 위해이를 반복합니다. 나는 작동하는 것을 사용해도 괜찮을 것입니다. 가장 좋은 데이터 유형은 무엇이라고 생각하십니까?
Samantha JT Star

1
Get과 일치하도록 Items의 데이터 유형을 IEnumerable <T>로 변경하거나 Items와 일치하도록 Get의 반환 유형을 ICollection <T>로 변경하는 것이 좋습니다. 나는이 두 가지가 방금 다르게 선언 된 동일한 기본 유형이라고 가정합니까? ToList () 또는 ToArray () 사용을 피하고 싶은 동일한 유형 인 경우 불필요한 메모리 할당 및 배열 복사를 수행합니다. 그들은 같은 유형이 아닌 경우에 당신은 어떤 전환해야
박사 앤드류 버넷 - 톰슨

나중에 항목을 사용하는 위치를 표시하기 위해 질문에 추가했습니다. 동일한 기본 유형을 말할 때 맞습니다.
Samantha JT Star

좋아, 그런 다음 변환 (느린 ToList / ToArray를 통해) 또는 캐스팅을 수행 할 필요가 없으므로 Get의 반환 유형을 변경합니다. 희망이 :) 도움이
박사 앤드류 버넷 - 톰슨
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.