c# - 什么是集合语义(在.NET中)?

标签 c# .net collections interface semantics

我需要在自己的课程中维护集合语义。您无法解释,集合语义是什么?据我了解,它是一组必须在类中实现的接口。是真的吗如果是的话,我该在课堂上具体实施什么?为什么?这两个接口(ICollection和IEnumerable)是否足够,还是仅是最必要的接口?

我正在使用this article作为帮助编写循环链表。

最佳答案

.NET中有很多集合类型,它们都有一些共同的行为,例如:


您可以使用foreach枚举它们
他们有一个Count属性
您可以使用Add方法添加项目
等等...


从集合类型可以预料到这种行为,您猜对了:都在ICollection<T>界面中。让我们看一下接口层次结构:


IEnumerable<T>允许使用foreach枚举您的班级
ICollection<T>是表示集合的IEnumerable<T>

它允许检索项目Count
您可能可以从集合中Add / Remove / Clear个项目
集合可能是只读的,在这种情况下,IsReadOnly应该返回true
还有其他一些辅助方法:Contains / CopyTo

IList<T>是允许通过索引访问项目的ICollection<T>

它添加了一个索引器
一些与索引相关的功能:Insert / RemoveAt
IndexOf



您应该实现哪个接口取决于语义:

IEnumerable<T>只是一个可枚举的序列。只能通过使用代码来枚举一次,因为您永远不知道它在多个枚举中的表现方式。如果多次枚举IEnumerable<T>,诸如ReSharper之类的工具甚至会发出警告。
当然,大多数时候您可以安全地枚举它多次,但是有些时候您不应该这样做。例如,一个枚举可以执行一个SQL查询(例如,以Linq-to-SQL为例)。

通过定义一个函数来实现IEnumerable<T>GetEnumerator返回en IEnumerator<T>。枚举数是一个对象,是一种指向序列中当前元素的指针。它可以返回该Current值,并且可以使用MoveNext移至下一个元素。它也是一次性的(并在foreach的枚举末尾放置)。

让我们分解一个foreach循环:

IEnumerable<T> sequence = ... // Whatever
foreach (T item in sequence)
    DoSomething(item);


这等效于以下内容:

IEnumerator<T> enumerator = null;
try
{
    enumerator = sequence.GetEnumerator();
    while (enumerator.MoveNext())
    {
        T item = enumerator.Current;
        DoSomething(item);
    }
}
finally
{
    if (enumerator != null)
        enumerator.Dispose();
}


记录上,严格要求实现IEnumerable才能使类可用于foreach。鸭子在这里打字就足够了,但我的话太多了。

当然,您可以使用yield关键字轻松实现该模式:

public static IEnumerable<int> GetAnswer()
{
    yield return 42;
}


这将创建一个私有类,该类将为您实现IEnumerable<int>,因此您不必这样做。

ICollection<T>表示一个集合,可以安全地多次枚举。但是您真的不知道它是什么样的收藏。它可以是集合,列表,字典等。

这就是集合的语义。

一些例子:


T[]-即使您不能ICollection<T> / Add,它也会实现Remove
List<T>
HashSet<T>-一个很好的集合示例,但没有列表
Dictionary<TKey, TValue>-是的,这是一个ICollection<KeyValuePair<TKey, TValue>>
LinkedList<T>
ObservableCollection<T>


IList<T>让您知道集合的类型,该集合使您可以轻松地按索引访问元素(即O(1)时间)。

对于您的循环链表,情况并非如此,因为它不仅需要O(n)时间,而且首先没有有意义的索引。

一些例子:


T[]
List<T>
ObservableCollection<T>


请注意,例如HashSet<T>Dictionary<TKey, TValue>不再在列表中。这些不是列表。 LinkedList<T>在语义上是一个列表,但在O(1)时间内不提供按索引的访问(它需要O(n))。

我应该提到在.NET 4.5中存在的只读等效项:IReadOnlyCollection<out T>IReadOnlyList<out T>。这些对于它们提供的协方差很好。

关于c# - 什么是集合语义(在.NET中)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26202036/

相关文章:

java - 为什么 Java 集合框架不包含树和图

c# - 我正在尝试为白天/夜晚的配色方案设计一个解决方案,但卡住了

c# - 将数据从服务器发送回客户端

c# - Bloomberg API - 获取政府债券列表

c# - ASP.NET MVC AntiCrsf token 是否依赖 machinekey

.NET:如何在 Active Directory 中查找用户?

c# - 如何使用 C# 填写 Google 表单

c# - 如何知道给定的字体是否是 OpenType 字体

java - 在java中创建一个二维表

php - 如何访问集合中的特定属性?