CA1010: Samlingar bör implementera generiskt gränssnitt
Property | Värde |
---|---|
Regel-ID | CA1010 |
Title | Samlingar bör implementera ett allmänt gränssnitt |
Kategori | Designa |
Korrigeringen är icke-bakåtkompatibel | Icke-icke-bryta |
Aktiverad som standard i .NET 9 | Nej |
Orsak
En typ implementerar gränssnittet men implementerar System.Collections.IEnumerable System.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:
- System.Collections.Generic.List<T>
- System.Collections.Generic.Queue<T>
- System.Collections.Generic.Stack<T>
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:
- System.Collections.Generic.IEnumerable<T>
- System.Collections.Generic.ICollection<T>
- System.Collections.Generic.IList<T>
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:
- Implementera det allmänna gränssnittet.
- Ändra basklassen till en typ som redan implementerar både allmänna och icke-generiska gränssnitt, till exempel
Collection<T>
klassen.
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.
Relaterade regler
- CA1005: Undvik överdrivna parametrar för generiska typer
- CA1000: Deklarera inte statiska medlemmar på generiska typer
- CA1002: Exponera inte allmänna listor
- CA1003: Använda allmänna händelsehanterarinstanser