CA1010: Coleções devem implementar uma interface genérica
Property | Valor |
---|---|
ID da regra | CA1010 |
Título | Coleções devem implementar uma interface genérica |
Categoria | Projetar |
Correção interruptiva ou sem interrupção | Sem interrupção |
Habilitado por padrão no .NET 9 | Não |
Causa
Um tipo implementa a interface System.Collections.IEnumerable, mas não implementa a interface System.Collections.Generic.IEnumerable<T>, e o assembly que o contém tem como destino .NET. Esta regra ignora tipos que implementam System.Collections.IDictionary.
Por padrão, essa regra apenas analisa os tipos visíveis externamente, mas isso é configurável. Você também pode configurar interfaces adicionais para exigir que uma interface genérica seja implementada.
Descrição da regra
Para ampliar a usabilidade de uma coleção, implemente uma das interfaces da coleção genéricas. Em seguida, a coleção pode ser usada para preencher tipos de coleção genéricos, como o seguinte:
- System.Collections.Generic.List<T>
- System.Collections.Generic.Queue<T>
- System.Collections.Generic.Stack<T>
Como corrigir violações
Para corrigir uma violação desta regra, implemente uma das seguintes interfaces de coleção genéricas:
- System.Collections.Generic.IEnumerable<T>
- System.Collections.Generic.ICollection<T>
- System.Collections.Generic.IList<T>
Quando suprimir avisos
É seguro suprimir um aviso desta regra; no entanto, o uso da coleção será mais limitado.
Suprimir um aviso
Para suprimir apenas uma violação, adicione diretivas de pré-processador ao arquivo de origem a fim de desabilitar e, em seguida, reabilitar a regra.
#pragma warning disable CA1010
// The code that's violating the rule is on this line.
#pragma warning restore CA1010
Para desabilitar a regra em um arquivo, uma pasta ou um projeto, defina a severidade como none
no arquivo de configuração.
[*.{cs,vb}]
dotnet_diagnostic.CA1010.severity = none
Para obter mais informações, confira Como suprimir avisos de análise de código.
Configurar código para analisar
Use as opções a seguir para configurar em quais partes da base de código essa regra deve ser executada.
Você pode configurar essas opções apenas para essa regra, para todas as regras às quais ela se aplica ou para todas as regras nessa categoria (Design) às quais ela se aplica. Para saber mais, confira Opções de configuração de regra de qualidade de código.
Incluir superfícies de API específicas
É possível configurar em quais partes da base de código essa regra deverá ser executada, com base na acessibilidade. Por exemplo, para especificar que a regra deverá ser executada apenas na superfície de API não pública, adicione o seguinte par chave-valor a um arquivo .editorconfig no projeto:
dotnet_code_quality.CAXXXX.api_surface = private, internal
Interfaces genéricas adicionais necessárias
Você pode configurar a lista de nomes de interface (separados por |
) com sua interface genérica totalmente qualificada exigida (separada por ->
).
Formatos de interface permitidos:
- Apenas o nome da interface (inclui todas as interfaces com o nome, independentemente do tipo ou do namespace que o contenham).
- Nomes totalmente qualificados no formato de ID de documentação do símbolo, com um prefixo opcional
T:
.
Exemplos:
Valor de opção | Resumo |
---|---|
dotnet_code_quality.CA1010.additional_required_generic_interfaces = ISomething->System.Collections.Generic.IEnumerable`1 |
Espera-se que todos os tipos que implementam ISomething , independentemente de seu namespace, também implementem System.Collections.Generic.IEnumerable<T>. |
dotnet_code_quality.CA1010.additional_required_generic_interfaces = T:System.Collections.IDictionary->T:System.Collections.Generic.IDictionary`2 |
É esperado que todos os tipos que implementam System.Collections.IDictionary também implementem System.Collections.Generic.IDictionary<TKey,TValue>. |
Exemplo
O exemplo a seguir mostra uma classe que deriva da classe não genérica CollectionBase
e viola essa regra.
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 corrigir uma violação dessa regra, siga um destes procedimentos:
- Implemente a interface genérica.
- Altere a classe base para um tipo que já implemente as interfaces genéricas e não genéricas, como a classe
Collection<T>
.
Correção por implementação de interface
O exemplo a seguir corrige a violação implementando essas interfaces genéricas: IEnumerable<T>, ICollection<T> e 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()
{
}
}
}
Correção por mudança de classe base
O exemplo a seguir corrige a violação alterando a classe base da coleção de classe não genérica CollectionBase
para classe genérica Collection<T>
(Collection(Of T)
no Visual Basic).
public class Book
{
public Book()
{
}
}
public class BookCollection : Collection<Book>
{
public BookCollection()
{
}
}
A alteração da classe base de uma classe já lançada é considerada uma alteração importante para os consumidores existentes.
Regras relacionadas
- CA1005: Evitar parâmetros excessivos em tipos genéricos
- CA1000: Não declarar membros estáticos em tipos genéricos
- CA1002: Não expor listas genéricas
- CA1003: Usar instâncias do manipulador de eventos genérico