CA2213 : Les champs pouvant être supprimés doivent l’être
Propriété | Value |
---|---|
Identificateur de la règle | CA2213 |
Titre | Les champs pouvant être supprimés doivent l’être |
Catégorie | Utilisation |
Le correctif est cassant ou non cassant | Sans rupture |
Activé par défaut dans .NET 8 | Non |
Cause
Un type qui implémente System.IDisposable déclare des champs de types qui implémentent également IDisposable. La méthode Dispose du champ n’est pas appelée par la méthode Dispose du type déclarant.
Description de la règle
Un type est responsable de la suppression de toutes ses ressources non managées. La règle CA2213 vérifie si un type pouvant être supprimé (c’est-à-dire qui implémente IDisposable) T
déclare un champ F
qui est une instance d’un type FT
pouvant être supprimé. Pour chaque champ F
auquel est affecté un objet créé localement dans les méthodes ou initialiseurs du type conteneur T
, la règle tente de localiser un appel à FT.Dispose
. La règle recherche les méthodes appelées par T.Dispose
et un niveau inférieur (c’est-à-dire les méthodes appelées par les méthodes appelées par T.Dispose
).
Notes
Outre les cas spéciaux, la règle CA2213 se déclenche uniquement pour les champs auxquels est affecté un objet pouvant être supprimé et créé localement dans les méthodes et initialiseurs du type conteneur. Si l’objet est créé ou affecté en dehors du type T
, la règle ne se déclenche pas. Cela réduit le bruit dans les cas où le type conteneur n’est pas responsable de la suppression de l’objet.
Cas particuliers
La règle CA2213 peut également être déclenchée pour les champs des types suivants, même si l’objet qui leur est attribué n’est pas créé localement :
Le passage d’un objet d’un de ces types à un constructeur, puis son affectation à un champ indique un transfert de la propriété de suppression vers le type nouvellement construit. Autrement dit, le type nouvellement construit est maintenant responsable de la suppression de l’objet. Si l’objet n’est pas supprimé, une violation de CA2213 se produit.
Comment corriger les violations
Pour corriger une violation de cette règle, appelez Dispose sur les champs qui sont des types implémentant IDisposable.
Quand supprimer les avertissements
Vous pouvez supprimer un avertissement de cette règle en toute sécurité si :
- Le type marqué n’est pas responsable de la libération de la ressource détenue par le champ (c’est-à-dire le type n’a pas la propriété de suppression)
- L’appel à Dispose se produit à un niveau d’appel plus profond que les vérifications de la règle
- La propriété de suppression du champs ou des champs n’est pas détenue par le type conteneur.
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 CA2213
// The code that's violating the rule is on this line.
#pragma warning restore CA2213
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.CA2213.severity = none
Pour plus d’informations, consultez Comment supprimer les avertissements de l’analyse de code.
Exemple
L’extrait de code suivant montre un type TypeA
implémentant IDisposable.
public class TypeA : IDisposable
{
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// Dispose managed resources
}
// Free native resources
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
// Disposable types implement a finalizer.
~TypeA()
{
Dispose(false);
}
}
L’extrait de code suivant montre un type TypeB
qui enfreint la règle CA2213 en déclarant un champ aFieldOfADisposableType
en tant que type pouvant être supprimé (TypeA
) et en n’appelant Dispose pas sur le champ.
public class TypeB : IDisposable
{
// Assume this type has some unmanaged resources.
TypeA aFieldOfADisposableType = new TypeA();
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
// Dispose of resources held by this instance.
// Violates rule: DisposableFieldsShouldBeDisposed.
// Should call aFieldOfADisposableType.Dispose();
disposed = true;
// Suppress finalization of this disposed instance.
if (disposing)
{
GC.SuppressFinalize(this);
}
}
}
public void Dispose()
{
if (!disposed)
{
// Dispose of resources held by this instance.
Dispose(true);
}
}
// Disposable types implement a finalizer.
~TypeB()
{
Dispose(false);
}
}
Pour corriger la violation, appelez Dispose()
sur le champ pouvant être supprimé :
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
// Dispose of resources held by this instance.
aFieldOfADisposableType.Dispose();
disposed = true;
// Suppress finalization of this disposed instance.
if (disposing)
{
GC.SuppressFinalize(this);
}
}
}