CA1010: Collections should implement generic interface
TypeName |
CollectionsShouldImplementGenericInterface |
CheckId |
CA1010 |
Category |
Microsoft.Design |
Breaking Change |
Non-breaking |
Cause
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.
Rule Description
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:
How to Fix Violations
To fix a violation of this rule, implement one of the following generic collection interfaces:
When to Suppress Warnings
It is safe to suppress a warning from this rule; however, the collection will have a more limited use.
Example Violation
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.
Fix by Base Class Change
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.
Fix by Interface Implementation
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()
{
}
}
}
}
Related Rules
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
CA1007: Use generics where appropriate