CA1010: Le raccolte devono implementare un'interfaccia generica
Proprietà | valore |
---|---|
ID regola | CA1010 |
Titolo | Le raccolte devono implementare un'interfaccia generica |
Categoria | Progettazione |
Correzione che causa un'interruzione o un'interruzione | Nessuna interruzione |
Abilitato per impostazione predefinita in .NET 8 | No |
Causa
Un tipo implementa l'interfaccia System.Collections.IEnumerable ma non implementa l'interfaccia System.Collections.Generic.IEnumerable<T> e l'assembly contenitore è destinato a .NET. Questa regola ignora i tipi che implementano System.Collections.IDictionary.
Per impostazione predefinita, questa regola esamina solo i tipi visibili esternamente, ma è configurabile. È anche possibile configurare interfacce aggiuntive per richiedere l'implementazione di un'interfaccia generica.
Descrizione regola
Per ampliare la possibilità di utilizzo di una raccolta, implementare una delle interfacce di raccolta generiche. È quindi possibile usare la raccolta per popolare tipi di raccolta generici, ad esempio i seguenti:
- System.Collections.Generic.List<T>
- System.Collections.Generic.Queue<T>
- System.Collections.Generic.Stack<T>
Come correggere le violazioni
Per correggere una violazione di questa regola, implementare una delle interfacce di raccolta generiche seguenti:
- System.Collections.Generic.IEnumerable<T>
- System.Collections.Generic.ICollection<T>
- System.Collections.Generic.IList<T>
Quando eliminare gli avvisi
È sicuro eliminare un avviso da questa regola; Tuttavia, l'uso della raccolta sarà più limitato.
Eliminare un avviso
Se si vuole eliminare una singola violazione, aggiungere direttive del preprocessore al file di origine per disabilitare e quindi riabilitare la regola.
#pragma warning disable CA1010
// The code that's violating the rule is on this line.
#pragma warning restore CA1010
Per disabilitare la regola per un file, una cartella o un progetto, impostarne la gravità none
su nel file di configurazione.
[*.{cs,vb}]
dotnet_diagnostic.CA1010.severity = none
Per altre informazioni, vedere Come eliminare gli avvisi di analisi del codice.
Configurare il codice da analizzare
Usare le opzioni seguenti per configurare le parti della codebase in cui eseguire questa regola.
È possibile configurare queste opzioni solo per questa regola, per tutte le regole a cui si applica o per tutte le regole in questa categoria (Progettazione) a cui si applica. Per altre informazioni, vedere Opzioni di configurazione delle regole di qualità del codice.
Includere superfici API specifiche
È possibile configurare le parti della codebase in modo da eseguire questa regola in base all'accessibilità. Ad esempio, per specificare che la regola deve essere eseguita solo sulla superficie dell'API non pubblica, aggiungere la coppia chiave-valore seguente a un file con estensione editorconfig nel progetto:
dotnet_code_quality.CAXXXX.api_surface = private, internal
Interfacce generiche aggiuntive necessarie
È possibile configurare l'elenco di nomi di interfaccia (separati da |
) con l'interfaccia generica completa richiesta (separata da ->
).
Formati di interfaccia consentiti:
- Solo nome interfaccia (include tutte le interfacce con il nome, indipendentemente dal tipo o dallo spazio dei nomi contenitore).
- Nomi completi nel formato ID della documentazione del simbolo con un prefisso facoltativo
T:
.
Esempi:
Valore opzione | Riepilogo |
---|---|
dotnet_code_quality.CA1010.additional_required_generic_interfaces = ISomething->System.Collections.Generic.IEnumerable`1 |
Tutti i tipi che implementano ISomething indipendentemente dallo spazio dei nomi devono implementare System.Collections.Generic.IEnumerable<T>anche . |
dotnet_code_quality.CA1010.additional_required_generic_interfaces = T:System.Collections.IDictionary->T:System.Collections.Generic.IDictionary`2 |
Tutti i tipi che implementano System.Collections.IDictionary devono implementare System.Collections.Generic.IDictionary<TKey,TValue>anche . |
Esempio
Nell'esempio seguente viene illustrata una classe che deriva dalla classe non generica CollectionBase
e viola questa regola.
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);
}
}
Per correggere una violazione di questa regola, eseguire una delle operazioni seguenti:
- Implementare l'interfaccia generica.
- Modificare la classe di base in un tipo che implementa già le interfacce generiche e non generiche, ad esempio la
Collection<T>
classe .
Correzione per implementazione dell'interfaccia
Nell'esempio seguente viene risolta la violazione implementando queste interfacce generiche: 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()
{
}
}
}
Correzione in base alla modifica della classe di base
Nell'esempio seguente viene risolta la violazione modificando la classe base della raccolta dalla classe non generica CollectionBase
alla classe generica Collection<T>
(Collection(Of T)
in Visual Basic).
public class Book
{
public Book()
{
}
}
public class BookCollection : Collection<Book>
{
public BookCollection()
{
}
}
La modifica della classe base di una classe già rilasciata viene considerata una modifica di rilievo ai consumer esistenti.
Regole correlate
- CA1005: Evitare un uso eccessivo di parametri nei tipi generici
- CA1000: Non dichiarare membri statici su tipi generici
- CA1002: Non esporre elenchi generici
- CA1003: Usare istanze di gestori eventi generici