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

Voir aussi