为啥 ICollection 索引在实例化时不起作用?

Posted

技术标签:

【中文标题】为啥 ICollection 索引在实例化时不起作用?【英文标题】:Why ICollection index does not work when instantiated?为什么 ICollection 索引在实例化时不起作用? 【发布时间】:2010-12-24 22:37:28 【问题描述】:

当我们将参数声明为 ICollection 并将对象实例化为 List 时,为什么我们不能检索索引?即

ICollection<ProductDTO> Products = new List<ProductDTO>();
Products.Add(new ProductDTO(1,"Pen"));
Products.Add(new ProductDTO(2,"Notebook"));

那么,这将不起作用:

ProductDTO product = (ProductDTO)Products[0];

我缺少什么? [是的,我们可以使用 List 作为声明,它可以工作,但我不想声明为列表,例如:

List&lt;ProductDTO&gt; Products = new List&lt;ProductDTO&gt;();

]

【问题讨论】:

你的意思是Products.Add(new ProductDTO(1,"Pen")); 这是实际的例子吗? List 和 ICollection 都没有用于接受两个参数的 Add 方法的重载? 【参考方案1】:

使用 LINQ,您可以这样做:

ProductDTO product = (ProductDTO)Products.ElementAt(0);

【讨论】:

【参考方案2】:

ICollection 接口没有声明索引器,因此您不能使用索引通过该类型的引用来获取元素。

您也许可以尝试IList,它增加了一些功能,同时仍然是抽象的。当然,这可能会影响其他设计决策,所以我会仔细研究。

【讨论】:

当你说设计决策时。你的意思是?使用 IList 或 ICollection 的最佳方法是什么? @Inanikian 没有“最佳”;这取决于上下文。如果您必须使用 IList 中的方法,比如说您需要索引/排序,那么 IList 可能是需要的最佳接口类型。另一方面,如果您只关心计数、添加、删除和枚举项目,但从不按索引,并且不希望对具有索引器和所有其他功能的类强加附加功能的要求IList 暗示你无论如何都不会使用,那么最好只需要你需要的东西,例如,ICollection(或者甚至 IEnumerable,如果你不修改任何东西)。 【参考方案3】:

ICollection 没有定义索引器。

ICollection Non-Generic

ICollection Generic

【讨论】:

您的链接指向非泛型 ICollection,您应将其重新指向泛型表单 @msdn.microsoft.com/en-us/library/92t2ye13.aspx @BasicallyMoney 有时只需要简短的回答。 简洁的答案阅读起来会更快。用户不喜欢阅读,记得吗? :)【参考方案4】:

那么这将起作用:

ProductDTO product = ((IList<ProductDTO>)Products)[0];

原因是编译器评估左值,即'='左侧的变量,以找出它知道的方法和属性可以在编译时访问。这称为静态类型化,通过静态知道成员始终可访问,确保可以在运行时直接访问对象成员。

【讨论】:

这消除了使用接口提供的抽象的好处:如果稍后将 Products 更改为 List 以外的其他内容,则上面的代码将被破坏,因为它对底层类型进行了假设表演时。 是的,但它修复了 OP 抱怨的单一语句。 你和我对修复这个词有不同的定义! ;-) 你需要再读一遍我的评论:它改变了一个 single 语句。我从来没有说过我解决了问题的原因。你不能总是从外观上称它为铁锹,在编程世界中所谓的 fix【参考方案5】:

基本问题是 ICollection 没有定义索引。对于 List,这是通过 IList 的实现来完成的。

试试这个:

IList<ProductDTO> Products = new List<ProductDTO>(); 

或者,当您需要通过索引访问元素时,您可以继续使用 ICollection 并转换为数组:

ICollection<ProductDTO> Products = new List<ProductDTO>();        
ProductDTO z = Products.ToArray()[0];

【讨论】:

ICollection&lt;&gt; 没有 ToArray 方法 - 只有 List&lt;&gt;。你需要CopyTo 取决于 .net 的版本。 ToArray() 是 3.x .net 框架的扩展方法。【参考方案6】:

使用 Linq,您可以访问 ICollection 中特定索引处的元素,如下所示:

myICollection.AsEnumerable().ElementAt(myIndex);

【讨论】:

【参考方案7】:

您也可以使用扩展方法将其转换为ProductDTO

的(列表、数组)
ICollection<ProductDTO> Products = new List<ProductDTO>();
var productsList = Products.ToList();

那么你可以这样使用它:

productsList[index]

【讨论】:

以上是关于为啥 ICollection 索引在实例化时不起作用?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Desktop.Open() 在安装 MagicISO 时不起作用

为啥输入在由 React 生成时不起作用

为啥我的函数在调用时不起作用? [关闭]

为啥“switch”语句在设置 UICollectionView 的标题时不起作用?

为啥 == 在比较具有相同 int 值的两个对象类型变量时不起作用

为啥 WPF 绑定在绑定到元素本身的标签时不起作用