Udostępnij za pośrednictwem


CA1010: Kolekcje powinny implementować interfejs generyczny

Właściwości Wartość
Identyfikator reguły CA1010
Tytuł Kolekcje powinny implementować interfejs ogólny
Kategoria Projektowanie
Poprawka łamiąca lub nienaruszająca Niezgodność
Domyślnie włączone na platformie .NET 10 Nie.
Zastosowane języki C# i Visual Basic

Przyczyna

Typ implementuje interfejs System.Collections.IEnumerable, ale nie implementuje interfejsu System.Collections.Generic.IEnumerable<T>, a zawierający zestaw jest skierowany na platformę .NET. Ta reguła ignoruje typy, które implementują System.Collections.IDictionary.

Domyślnie ta reguła analizuje tylko typy widoczne zewnętrznie, ale można to skonfigurować. Można również skonfigurować dodatkowe interfejsy, aby wymagać zaimplementowania interfejsu ogólnego.

Opis reguły

Aby poszerzyć użyteczność kolekcji, zaimplementuj jeden z interfejsów kolekcji generycznej. Następnie można użyć kolekcji do wypełniania typów kolekcji ogólnych, takich jak:

Jak naprawić naruszenia

Aby naprawić naruszenie tej reguły, zaimplementuj jeden z następujących interfejsów kolekcji ogólnych:

Kiedy pomijać ostrzeżenia

Można bezpiecznie zignorować ostrzeżenie w ramach tej reguły; jednak użycie kolekcji będzie bardziej ograniczone.

Pomijanie ostrzeżenia

Jeśli chcesz po prostu pominąć pojedyncze naruszenie, dodaj dyrektywy preprocesora do pliku źródłowego, aby wyłączyć, a następnie ponownie włączyć regułę.

#pragma warning disable CA1010
// The code that's violating the rule is on this line.
#pragma warning restore CA1010

Aby wyłączyć regułę dla pliku, folderu lub projektu, ustaw jego ważność na none w pliku konfiguracji.

[*.{cs,vb}]
dotnet_diagnostic.CA1010.severity = none

Aby uzyskać więcej informacji, zobacz Jak pominąć ostrzeżenia dotyczące analizy kodu.

Konfigurowanie kodu do analizowania

Użyj poniższych opcji, aby skonfigurować, na które części bazy kodu ma być stosowana ta reguła.

Możesz skonfigurować te opcje tylko dla tej reguły, dla wszystkich reguł, do których mają zastosowanie, lub dla wszystkich reguł w tej kategorii (Design), do których mają zastosowanie. Aby uzyskać więcej informacji, zobacz Opcje konfiguracji reguły jakości kodu.

Uwzględnij określone powierzchnie interfejsu API

Możesz skonfigurować, na które części bazy kodu ma być stosowana ta reguła, na podstawie ich poziomu dostępu, ustawiając opcję api_surface. Aby na przykład określić, że reguła powinna być uruchamiana tylko na powierzchni niepublicznego interfejsu API, dodaj następującą parę klucz-wartość do pliku editorconfig w projekcie:

dotnet_code_quality.CAXXXX.api_surface = private, internal

Notatka

Zastąp część XXXXCAXXXX identyfikatorem odpowiedniej reguły.

Dodatkowe wymagane interfejsy ogólne

Listę nazw interfejsów (oddzielonych znakami |) można skonfigurować przy użyciu wymaganego w pełni kwalifikowanego interfejsu ogólnego (oddzielonego przez ->).

Dozwolone formaty interfejsu:

  • Tylko nazwa interfejsu (zawiera wszystkie interfejsy o nazwie, niezależnie od typu zawierającego lub przestrzeni nazw).
  • W pełni kwalifikowane nazwy w formacie identyfikatora dokumentacji symbolu z opcjonalnym T: prefiksem.

Przykłady:

Wartość opcji Podsumowanie
dotnet_code_quality.CA1010.additional_required_generic_interfaces = ISomething->System.Collections.Generic.IEnumerable`1 Oczekuje się również, że wszystkie typy, które implementują ISomething, niezależnie od przestrzeni nazw, będą również implementować System.Collections.Generic.IEnumerable<T>.
dotnet_code_quality.CA1010.additional_required_generic_interfaces = T:System.Collections.IDictionary->T:System.Collections.Generic.IDictionary`2 Oczekuje się, że wszystkie typy implementujące System.Collections.IDictionary również zaimplementują System.Collections.Generic.IDictionary<TKey,TValue>.

Przykład

W poniższym przykładzie przedstawiono klasę, która pochodzi z klasy niegenerycznej CollectionBase i narusza tę regułę.

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);
    }
}

Aby naprawić naruszenie tej reguły, wykonaj jedną z następujących czynności:

Poprawka implementacji interfejsu

Poniższy przykład naprawia naruszenie przez zaimplementowanie tych ogólnych interfejsów: IEnumerable<T>, ICollection<T>i 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()
        {
        }
    }
}

Poprawka poprzez zmianę klasy bazowej

Poniższy przykład naprawia naruszenie, zmieniając klasę bazową kolekcji z klasy niegenerycznej CollectionBase na ogólną Collection<T> (Collection(Of T) w Visual Basic).

public class Book
{
    public Book()
    {
    }
}

public class BookCollection : Collection<Book>
{
    public BookCollection()
    {
    }
}

Zmiana klasy bazowej już wydanej klasy jest uważana za zmianę powodującą niezgodność dla istniejących odbiorców.

Zobacz też