CA1010 : Les collections doivent implémenter une interface générique
Propriété | Value |
---|---|
Identificateur de la règle | CA1010 |
Titre | Les collections doivent implémenter une interface générique |
Catégorie | Conception |
Le correctif est cassant ou non cassant | Sans rupture |
Activée par défaut dans .NET 9 | Non |
Cause
Un type implémente l’interface System.Collections.IEnumerable, mais n’implémente pas l’interface System.Collections.Generic.IEnumerable<T>, et l’assembly contenant cible .NET. Cette règle ignore les types qui implémentent System.Collections.IDictionary.
Par défaut, cette règle examine uniquement les types visibles en externe, mais elle est configurable. Vous pouvez également configurer des interfaces supplémentaires pour exiger l’implémentation d’une interface générique.
Description de la règle
Pour étendre la facilité d’utilisation d’une collection, implémentez l’une des interfaces de collection génériques. Ensuite, la collection peut être utilisée pour remplir des types de collection génériques, comme suit :
- System.Collections.Generic.List<T>
- System.Collections.Generic.Queue<T>
- System.Collections.Generic.Stack<T>
Comment corriger les violations
Pour corriger une violation de cette règle, implémentez l’une des interfaces de collection génériques suivantes :
- System.Collections.Generic.IEnumerable<T>
- System.Collections.Generic.ICollection<T>
- System.Collections.Generic.IList<T>
Quand supprimer les avertissements
Il est sûr de supprimer un avertissement de cette règle; toutefois, l’utilisation de la collection sera plus limitée.
Supprimer un avertissement
Si vous voulez supprimer une seule violation, ajoutez des directives de préprocesseur à votre fichier source pour désactiver et réactiver la règle.
#pragma warning disable CA1010
// The code that's violating the rule is on this line.
#pragma warning restore CA1010
Pour désactiver la règle sur un fichier, un dossier ou un projet, définissez sa gravité sur none
dans le fichier de configuration.
[*.{cs,vb}]
dotnet_diagnostic.CA1010.severity = none
Pour plus d’informations, consultez Comment supprimer les avertissements de l’analyse de code.
Configurer le code à analyser
Utilisez l’option suivante pour configurer les parties de votre codebase sur lesquelles exécuter cette règle.
Vous pouvez configurer ces options pour cette règle uniquement, pour toutes les règles auxquelles elles s’appliquent ou pour toutes les règles de cette catégorie (Conception) auxquelles elles s’appliquent. Pour plus d’informations, consultez Options de configuration des règles de qualité du code.
Inclure des surfaces d’API spécifiques
Vous pouvez configurer les parties de votre codebase sur lesquelles exécuter cette règle, en fonction de leur accessibilité. Par exemple, pour spécifier que la règle doit s’exécuter uniquement sur la surface d’API non publique, ajoutez la paire clé-valeur suivante à un fichier .editorconfig dans votre projet :
dotnet_code_quality.CAXXXX.api_surface = private, internal
Interfaces génériques supplémentaires requises
Vous pouvez configurer la liste des noms d’interface (séparés par |
) avec leur interface complète générique requise (séparée par ->
).
Formats d’interface autorisés :
- Nom de l’interface uniquement (inclut toutes les interfaces portant le nom, quel que soit le type ou l’espace de noms contenant).
- Les noms complets au format d’ID de documentation du symbole, avec un préfixe
T:
facultatif.
Exemples :
Valeur d'option | Récapitulatif |
---|---|
dotnet_code_quality.CA1010.additional_required_generic_interfaces = ISomething->System.Collections.Generic.IEnumerable`1 |
Tous les types qui implémentent ISomething indépendamment de son espace de noms doivent également implémenter System.Collections.Generic.IEnumerable<T>. |
dotnet_code_quality.CA1010.additional_required_generic_interfaces = T:System.Collections.IDictionary->T:System.Collections.Generic.IDictionary`2 |
Tous les types qui implémentent System.Collections.IDictionary sont censés également implémenter System.Collections.Generic.IDictionary<TKey,TValue>. |
Exemple
L’exemple suivant montre une classe qui dérive de la classe non générique CollectionBase
et enfreint cette règle.
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);
}
}
Pour corriger une infraction à cette règle, effectuez l’une des opérations suivantes :
- Implémentez l’interface générique.
- Remplacez la classe de base par un type qui implémente déjà les interfaces génériques et non génériques, comme la classe
Collection<T>
.
Corriger par implémentation de l’interface
L’exemple suivant corrige la violation en implémentant ces interfaces génériques : IEnumerable<T>, ICollection<T> et 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()
{
}
}
}
Correction par changement de classe de base
L’exemple suivant corrige la violation en changeant la classe de base de la collection de la classe non générique CollectionBase
en classe générique Collection<T>
(Collection(Of T)
en Visual Basic).
public class Book
{
public Book()
{
}
}
public class BookCollection : Collection<Book>
{
public BookCollection()
{
}
}
La modification de la classe de base d’une classe déjà publiée est considérée comme un changement cassant pour les consommateurs existants.
Règles associées
- CA1005 : Évitez trop de paramètres sur les types génériques
- CA1000 : Ne déclarez pas de membres statiques sur les types génériques
- CA1002 : N’exposez pas de listes génériques
- CA1003 : Utiliser les instances du gestionnaire d’événements génériques