CA1010: Las colecciones deben implementar la interfaz genérica
Propiedad | Value |
---|---|
Identificador de la regla | CA1010 |
Título | Las colecciones deben implementar la interfaz genérica |
Categoría | Diseño |
La corrección es problemática o no problemática | Poco problemático |
Habilitado de forma predeterminada en .NET 8 | No |
Causa
Un tipo implementa la interfaz System.Collections.IEnumerable, pero no implementa la interfaz System.Collections.Generic.IEnumerable<T>, y el ensamblado que lo contiene tiene como destino .NET. Esta regla ignora los tipos que implementan System.Collections.IDictionary.
De forma predeterminada, esta regla solo examina los tipos visibles externamente, pero es configurable. También puede configurar interfaces adicionales para requerir la implementación de una interfaz genérica.
Descripción de la regla
Para ampliar la utilidad de una colección, implemente una de las interfaces de colección genéricas. Entonces podrá utilizar la colección para rellenar tipos de colecciones genéricas, como las siguientes:
- System.Collections.Generic.List<T>
- System.Collections.Generic.Queue<T>
- System.Collections.Generic.Stack<T>
Cómo corregir infracciones
Para corregir una infracción de esta regla, implemente una de las interfaces de colección genéricas siguientes:
- System.Collections.Generic.IEnumerable<T>
- System.Collections.Generic.ICollection<T>
- System.Collections.Generic.IList<T>
Cuándo suprimir las advertencias
Es seguro suprimir una advertencia de esta regla. Sin embargo, el uso de la colección será más limitado.
Supresión de una advertencia
Si solo quiere suprimir una única infracción, agregue directivas de preprocesador al archivo de origen para deshabilitar y volver a habilitar la regla.
#pragma warning disable CA1010
// The code that's violating the rule is on this line.
#pragma warning restore CA1010
Para deshabilitar la regla de un archivo, una carpeta o un proyecto, establezca su gravedad en none
del archivo de configuración.
[*.{cs,vb}]
dotnet_diagnostic.CA1010.severity = none
Para obtener más información, consulte Procedimiento para suprimir advertencias de análisis de código.
Configuración del código para analizar
Use las opciones siguientes para configurar en qué partes del código base se va a ejecutar esta regla.
Puede configurar estas opciones solo para esta regla, para todas las reglas a las que se aplica o para todas las reglas de esta categoría (Diseño) a las que se aplica. Para más información, vea Opciones de configuración de reglas de calidad de código.
Incluir superficies de API específicas
Puede configurar en qué partes del código base ejecutar esta regla, en función de su accesibilidad. Por ejemplo, para especificar que la regla solo se debe ejecutar en la superficie de API no públicas, agregue el siguiente par clave-valor a un archivo .editorconfig en el proyecto:
dotnet_code_quality.CAXXXX.api_surface = private, internal
Interfaces genéricas adicionales necesarias
Puede configurar la lista de nombres de interfaz (separados por |
) con la interfaz genérica completa necesaria (separada por ->
).
Formatos de interfaz permitidos:
- Solo nombre de interfaz (incluye todas las interfaces con el nombre, con independencia del tipo contenedor o el espacio de nombres).
- Nombres completos en el formato de identificador de documentación del símbolo, con un prefijo
T:
opcional.
Ejemplos:
Valor de la opción | Resumen |
---|---|
dotnet_code_quality.CA1010.additional_required_generic_interfaces = ISomething->System.Collections.Generic.IEnumerable`1 |
Se espera que todos los tipos que implementan ISomething , con independencia de su espacio de nombres, implementen también System.Collections.Generic.IEnumerable<T>. |
dotnet_code_quality.CA1010.additional_required_generic_interfaces = T:System.Collections.IDictionary->T:System.Collections.Generic.IDictionary`2 |
Se espera que todos los tipos que implementan System.Collections.IDictionary también implementen System.Collections.Generic.IDictionary<TKey,TValue>. |
Ejemplo
En el ejemplo siguiente se muestra una clase que deriva de la clase no genérica CollectionBase
e infringe esta regla.
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);
}
}
Para corregir una infracción de esta regla, realice una de las siguientes acciones:
- Implementar la interfaz genérica.
- Cambie la clase base a un tipo que ya implemente las interfaces genérica y no genérica, como la clase
Collection<T>
.
Corrección mediante la implementación de interfaces
En el ejemplo siguiente se corrige la infracción mediante la implementación de estas interfaces genéricas: IEnumerable<T>, ICollection<T> y IList<T>.
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 => (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()
{
}
}
}
Corrección mediante el cambio de clase base
En el ejemplo siguiente se corrige la infracción cambiando la clase base de la colección de la clase CollectionBase
no genérica a la clase Collection<T>
genérica (Collection(Of T)
en Visual Basic).
public class Book
{
public Book()
{
}
}
public class BookCollection : Collection<Book>
{
public BookCollection()
{
}
}
El cambio de la clase base de una clase que ya se ha lanzado se considera un cambio importante para los consumidores existentes.
Reglas relacionadas
- CA1005: Evitar los parámetros excesivos en tipos genéricos
- CA1000: No declarar miembros estáticos en tipos genéricos
- CA1002: No exponer listas genéricas
- CA1003: Utilizar instancias genéricas de controlador de eventos