Share via


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 8 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:

Como corrigir violações

Para corrigir uma violação desta regra, implemente uma das seguintes interfaces de coleção genéricas:

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:

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.

Confira também