CA1010: Collections should implement generic interface
The new home for Visual Studio documentation is Visual Studio 2017 Documentation on docs.microsoft.com.
The latest version of this topic can be found at CA1010: Collections should implement generic interface.
TypeName|CollectionsShouldImplementGenericInterface|
|CheckId|CA1010|
|Category|Microsoft.Design|
|Breaking Change|Non-breaking|
An externally visible type implements the System.Collections.IEnumerable interface but does not implement the System.Collections.Generic.IEnumerable<T> interface, and the containing assembly targets .NET Framework 2.0. This rule ignores types that implement System.Collections.IDictionary.
To broaden the usability of a collection, implement one of the generic collection interfaces. Then the collection can be used to populate generic collection types such as the following:
To fix a violation of this rule, implement one of the following generic collection interfaces:
It is safe to suppress a warning from this rule; however, the collection will have a more limited use.
Description
The following example shows a class (reference type) that derives from the non-generic CollectionBase class, which violates this rule.
Code
using System; using System.Collections; namespace Samples { public class Book { public Book() { } } public class BookCollection : CollectionBase { public BookCollection() { } public void Add(Book value) { InnerList.Add(value); } public void Remove(Book value) { InnerList.Remove(value); } public void Insert(int index, Book value) { InnerList.Insert(index, value); } public Book this[int index] { get { return (Book)InnerList[index]; } set { InnerList[index] = value; } } public bool Contains(Book value) { return InnerList.Contains(value); } public int IndexOf(Book value) { return InnerList.IndexOf(value); } public void CopyTo(Book[] array, int arrayIndex) { InnerList.CopyTo(array, arrayIndex); } } }
Comments
To fix a violation of this violation, you should either implement the generic interfaces or change the base class to a type that already implements both the generic and non-generic interfaces, such as the Collection<T> class.
Description
The following example fixes the violation by changing the base class of the collection from the non-generic CollectionBase class to the generic Collection<T> (Collection(Of T) in Visual Basic) class.
Code
using System; using System.Collections.ObjectModel; namespace Samples { public class Book { public Book() { } } public class BookCollection : Collection<Book> { public BookCollection() { } } }
Comments
Changing the base class of an already released class is considered a breaking change to existing consumers.
Description
The following example fixes the violation by implementing these generic interfaces: IEnumerable<T>, ICollection<T>, and IList<T> (IEnumerable(Of T), ICollection(Of T), and IList(Of T) in Visual Basic).
Code
using System; using System.Collections; using System.Collections.Generic; namespace Samples { public class Book { public Book() { } } public class BookCollection : CollectionBase, IList<Book> { public BookCollection() { } int IList<Book>.IndexOf(Book item) { return this.List.IndexOf(item); } void IList<Book>.Insert(int location, Book item) { } Book IList<Book>.this[int index] { get { return (Book) this.List[index]; } set { } } void ICollection<Book>.Add(Book item) { } bool ICollection<Book>.Contains(Book item) { return true; } void ICollection<Book>.CopyTo(Book[] array, int arrayIndex) { } bool ICollection<Book>.IsReadOnly { get { return false; } } bool ICollection<Book>.Remove(Book item) { if (InnerList.Contains(item)) { InnerList.Remove(item); return true; } return false; } IEnumerator<Book> IEnumerable<Book>.GetEnumerator() { return new BookCollectionEnumerator(InnerList.GetEnumerator()); } private class BookCollectionEnumerator : IEnumerator<Book> { private IEnumerator _Enumerator; public BookCollectionEnumerator(IEnumerator enumerator) { _Enumerator = enumerator; } public Book Current { get { return (Book)_Enumerator.Current; } } object IEnumerator.Current { get { return _Enumerator.Current; } } public bool MoveNext() { return _Enumerator.MoveNext(); } public void Reset() { _Enumerator.Reset(); } public void Dispose() { } } } }
CA1005: Avoid excessive parameters on generic types
CA1000: Do not declare static members on generic types
CA1002: Do not expose generic lists
CA1006: Do not nest generic types in member signatures
CA1004: Generic methods should provide type parameter
CA1003: Use generic event handler instances