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.