无法从IEnumerable <T>转换为ICollection <T>


90

我定义了以下内容:

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)签名(特别是返回类型)的更多信息?
2012年

为什么不这样更改类型?public IEnumerable<Item> Items { get; set; }你有什么特殊的理由ICollection吗?
暗影巫师为您耳边

IEnumerable <T> Get(字符串pk);
萨曼莎JT星

Answers:


112

ICollection<T>IEnumerable<T>so继承,以分配结果

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添加了哪些附加功能?
萨曼莎JT星

7
ICollection<T>可以被操纵(有关详细信息,请参阅文档),而IEnumerable<T>只能枚举。
Anders Abel

我需要可以在其中运行不同的LINQ查询的东西。我不需要在列表中添加或执行类似操作。这是否意味着我最好使用ICollection。
萨曼莎JT星

LINQ工作在IEnumerable<T>这样IEnumerable<T>就够了在这种情况下。
Anders Abel

31

您不能直接从转换IEnumerable<T>ICollection<T>。您可以使用的ToList方法IEnumerable<T>将其转换为ICollection<T>

someICollection = SomeIEnumerable.ToList();


这对我有用。但这对我来说是个好主意,还是将IEnumerable用作Items的类型会更好。如果我使用IEnumerable,我是否可以这样做,以便以后在程序中需要时可以对Items执行更多操作?
萨曼莎JT星

ICollection已经实现IEnumerable。如果您担心可用的操作,我认为您应该选择ICollection。最好是先阅读两者之间的实际差异,然后再决定要实际使用的内容
Haris Hasan 2012年

我试图了解如果使用ToList()会有什么好处。获得数据后,我想对Items运行LINQ查询。
萨曼莎JT星

ToList()可以工作,但是正如您在评论中所述,Get()返回一个ICollection,所以实际上您只需要对ICollection <T>进行强制转换,或者更好的是,将Get的返回签名更改为ICollection <T>。 。使用ToList或ToArray可以使用,但也会产生不必要的创建内存/复制操作
Dr. Andrew Burnett-Thompson

您可以同时对IEnumerable和ICollection运行LINQ查询。优点..我现在所知道的是Count ICollection通过计算有多少项来维护count和IEnumerable返回结果。ICollection提供了Ienumerables不提供的其他删除方法
Haris Hasan

1

等待有关该问题的更多信息:

请提供有关物品类型和Get签名的更多信息

您可以尝试的两件事是:

  • 将_item.Get的返回值转换为(ICollection)
  • 其次使用_item.Get(“ 001”)。ToArray()或_item.Get(“ 001”)。ToList()

请注意,第二个将导致阵列副本的性能下降。如果Get的签名(返回类型)不是ICollection,则第一个不起作用,如果不是IEnumerable,则第二个将不起作用。


在您澄清问题并发表评论后,我将亲自向ICollection声明_item.Get(“ 001”)的返回类型。这意味着您无需进行任何涉及不必要的创建/复制操作的转换或转换(通过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(字符串pk); 项目用于保存返回的项目记录。稍后,我将遍历这些内容以创建报告。我可以使用任何可行的方法。您认为最佳的数据类型是什么?
萨曼莎JT星

1
我建议将Items的数据类型更改为IEnumerable <T>以匹配Get,或者将Get的返回类型更改为ICollection <T>以匹配Items。我假设这两个是相同的基础类型,只是声明不同?如果它们与您要避免使用ToList()或ToArray()的类型相同,因为它们会执行不必​​要的内存分配和数组复制。如果它们不是同一类型,则必须进行一些转换
Dr. Andrew Burnett-Thompson

我添加了问题以显示以后在哪里使用Items。说相同的基础类型时,您是正确的。
萨曼莎JT星

好的,那么我只需更改Get的返回类型,因为您无需进行任何转换(通过ToList / ToArray,这很慢)或强制转换。希望能对您有所帮助:)
Andrew Burnett-Thompson博士2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.