Share via


CA1010: Samlingar bör implementera generiskt gränssnitt

Property Värde
Regel-ID CA1010
Rubrik Samlingar bör implementera ett allmänt gränssnitt
Kategori Designa
Korrigeringen är icke-bakåtkompatibel Icke-icke-bryta
Aktiverad som standard i .NET 8 Nej

Orsak

En typ implementerar gränssnittet men implementerar System.Collections.IEnumerableSystem.Collections.Generic.IEnumerable<T> inte gränssnittet och de innehållande sammansättningsmålen .NET. Den här regeln ignorerar typer som implementerar System.Collections.IDictionary.

Som standard tittar den här regeln bara på externt synliga typer, men det kan konfigureras. Du kan också konfigurera ytterligare gränssnitt för att kräva att ett allmänt gränssnitt implementeras.

Regelbeskrivning

Om du vill bredda användbarheten för en samling implementerar du ett av de generiska samlingsgränssnitten. Sedan kan samlingen användas för att fylla i generiska samlingstyper, till exempel följande:

Så här åtgärdar du överträdelser

Om du vill åtgärda ett brott mot den här regeln implementerar du något av följande allmänna samlingsgränssnitt:

När du ska ignorera varningar

Det är säkert att ignorera en varning från den här regeln. Användningen av samlingen kommer dock att vara mer begränsad.

Ignorera en varning

Om du bara vill förhindra en enda överträdelse lägger du till förprocessordirektiv i källfilen för att inaktivera och aktiverar sedan regeln igen.

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

Om du vill inaktivera regeln för en fil, mapp eller ett projekt anger du dess allvarlighetsgrad till none i konfigurationsfilen.

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

Mer information finns i Så här utelämnar du kodanalysvarningar.

Konfigurera kod för analys

Använd följande alternativ för att konfigurera vilka delar av kodbasen som regeln ska köras på.

Du kan konfigurera dessa alternativ för just den här regeln, för alla regler som den gäller för eller för alla regler i den här kategorin (design) som den gäller för. Mer information finns i Konfigurationsalternativ för kodkvalitetsregel.

Inkludera specifika API-ytor

Du kan konfigurera vilka delar av kodbasen som ska köras med den här regeln baserat på deras tillgänglighet. Om du till exempel vill ange att regeln endast ska köras mot den icke-offentliga API-ytan lägger du till följande nyckel/värde-par i en .editorconfig-fil i projektet:

dotnet_code_quality.CAXXXX.api_surface = private, internal

Ytterligare obligatoriska allmänna gränssnitt

Du kan konfigurera listan med gränssnittsnamn (avgränsade |med ) med deras obligatoriska generiska fullständigt kvalificerade gränssnitt (avgränsat med ->).

Tillåtna gränssnittsformat:

  • Endast gränssnittsnamn (innehåller alla gränssnitt med namnet, oavsett vilken typ eller namnrymd som innehåller).
  • Fullständigt kvalificerade namn i symbolens dokumentations-ID-format med ett valfritt T: prefix.

Exempel:

Alternativvärde Sammanfattning
dotnet_code_quality.CA1010.additional_required_generic_interfaces = ISomething->System.Collections.Generic.IEnumerable`1 Alla typer som implementerar ISomething oavsett namnrymd förväntas också implementera System.Collections.Generic.IEnumerable<T>.
dotnet_code_quality.CA1010.additional_required_generic_interfaces = T:System.Collections.IDictionary->T:System.Collections.Generic.IDictionary`2 Alla typer som implementerar System.Collections.IDictionary förväntas också implementera System.Collections.Generic.IDictionary<TKey,TValue>.

Exempel

I följande exempel visas en klass som härleds från den icke-generiska CollectionBase klassen och som bryter mot den här regeln.

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

Gör något av följande för att åtgärda ett brott mot den här regeln:

Korrigering efter gränssnittsimplementering

I följande exempel åtgärdas överträdelsen genom att implementera dessa allmänna gränssnitt: IEnumerable<T>, ICollection<T>och 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()
        {
        }
    }
}

Korrigering efter basklassändring

I följande exempel åtgärdas överträdelsen genom att ändra basklassen för samlingen från den icke-generiska CollectionBase klassen till den generiska Collection<T> klassen (Collection(Of T) i Visual Basic).

public class Book
{
    public Book()
    {
    }
}

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

Att ändra basklassen för en redan publicerad klass anses vara en icke-bakåtkompatibel ändring av befintliga konsumenter.

Se även