Comparteix a través de


CA2213: Los campos descartables deben ser descartables

Propiedad Value
Identificador de la regla CA2213
Título Los campos descartables deben ser descartables
Categoría Uso
La corrección es problemática o no problemática Poco problemático
Habilitado de forma predeterminada en .NET 8 No

Causa

Un tipo que implementa System.IDisposable declara campos que son de tipos que también implementan IDisposable. El método Dispose del tipo declarativo no llama al método Dispose del campo.

Descripción de la regla

Un tipo es responsable de la eliminación de todos sus recursos no administrados. La regla CA2213 comprueba que un tipo descartable (es decir, un tipo que implementa IDisposable) T declare un campo F que sea una instancia de un tipo descartable FT. Para cada campo F que tiene asignado un objeto creado localmente dentro de los métodos o inicializadores del tipo contenedor T, la regla intenta localizar una llamada a FT.Dispose. La regla busca los métodos a los que llama T.Dispose y un nivel inferior (es decir, los métodos llamados por los métodos a los que llama T.Dispose).

Nota

Aparte de los casos especiales, la regla CA2213 se activa solo para los campos que tienen asignado un objeto descartable creado localmente dentro de los métodos e inicializadores del tipo contenedor. Si el objeto se crea o se asigna fuera del tipo T, la regla no se activa. Esto reduce el ruido en los casos en los que el tipo contenedor no posee la responsabilidad de descartar el objeto.

Casos especiales

La regla CA2213 también se puede activar para los campos de los siguientes tipos incluso si el objeto que tienen asignado no se crea localmente:

Pasar un objeto de uno de estos tipos a un constructor y, después, asignarlo a un campo indica una transferencia de la propiedad Dispose hacia el tipo recién construido. Es decir, el tipo recién construido ahora es responsable de descartar el objeto. Si el objeto no se descarta, se produce una infracción de la regla CA2213.

Cómo corregir infracciones

Para corregir una infracción de esta regla, llame a Dispose en los campos que sean de tipos que implementan IDisposable.

Cuándo suprimir las advertencias

Se puede suprimir una advertencia de esta regla si:

  • El tipo marcado no es responsable de liberar el recurso que contiene el campo (es decir, el tipo no tiene la propiedad Dispose).
  • La llamada a Dispose se produce en un nivel de llamada más profundo que las comprobaciones de la regla.
  • El tipo contenedor no contiene la propiedad Dispose de los campos.

Supresión de una advertencia

Si solo quiere suprimir una única infracción, agregue directivas de preprocesador al archivo de origen para deshabilitar y volver a habilitar la regla.

#pragma warning disable CA2213
// The code that's violating the rule is on this line.
#pragma warning restore CA2213

Para deshabilitar la regla de un archivo, una carpeta o un proyecto, establezca su gravedad en none del archivo de configuración.

[*.{cs,vb}]
dotnet_diagnostic.CA2213.severity = none

Para obtener más información, consulte Procedimiento para suprimir advertencias de análisis de código.

Ejemplo

En el fragmento de código siguiente se muestra un tipo TypeA que implementa 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);
    }
}

En el fragmento de código siguiente se muestra un tipo TypeB que infringe la regla CA2213 al declarar un campo aFieldOfADisposableType como un tipo descartable (TypeA) y no llamar a Dispose en el campo.

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

Para corregir la infracción, llame a Dispose() en el campo descartable:

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

Consulte también