Edit

Share via


Resolve warnings related to the using statements and using declarations

This article covers the following compiler errors:

  • CS0245: Destructors and object.Finalize cannot be called directly. Consider calling IDisposable.Dispose if available.
  • CS0728: Possibly incorrect assignment to local variable which is the argument to a using or lock statement. The Dispose call or unlocking will happen on the original value of the local.
  • CS1674: Type used in a using statement must be implicitly convertible to 'System.IDisposable'.
  • CS8410: 'Type used in an asynchronous using statement must be implicitly convertible to 'System.IAsyncDisposable' or implement a suitable 'DisposeAsync' method.
  • CS8417: Type used in an asynchronous using statement must implement 'System.IAsyncDisposable' or implement a suitable 'DisposeAsync' method. Did you mean 'using' rather than 'await using'?
  • CS8418: Type used in a using statement must implement 'System.IDisposable'. Did you mean 'await using' rather than 'using'?
  • CS8647: A using variable cannot be used directly within a switch section (consider using braces).
  • CS8648: A goto cannot jump to a location after a using declaration.
  • CS8649: A goto cannot jump to a location before a using declaration within the same block.
  • CS9229: Modifiers cannot be placed on using declarations.

Implementing IDisposable and IAsyncDisposable

The following compiler errors and warnings indicate issues with implementing or using the dispose pattern:

  • CS0245: Destructors and object.Finalize cannot be called directly. Consider calling IDisposable.Dispose if available.
  • CS1674: Type used in a using statement must be implicitly convertible to 'System.IDisposable'.
  • CS8410: Type used in an asynchronous using statement must be implicitly convertible to 'System.IAsyncDisposable' or implement a suitable 'DisposeAsync' method.
  • CS8417: Type used in an asynchronous using statement must implement 'System.IAsyncDisposable' or implement a suitable 'DisposeAsync' method. Did you mean 'using' rather than 'await using'?
  • CS8418: Type used in a using statement must implement 'System.IDisposable'. Did you mean 'await using' rather than 'using'?

The using statement ensures proper disposal of resources at the end of the using block. To use a type with a using statement, it must implement the appropriate disposal interface. For synchronous using statements, the type must implement IDisposable. For asynchronous await using statements, the type must implement IAsyncDisposable.

  • Cannot call Finalize directly (CS0245): You can't directly call a destructor or the Object.Finalize method. The garbage collector automatically invokes finalizers when objects are no longer referenced. For deterministic cleanup, implement IDisposable and call the Dispose method instead.
  • Type must implement IDisposable (CS1674): Only types that implement IDisposable can be used in a using statement. Value types don't implement this interface, and generic type parameters without proper constraints can't be assumed to be disposable. Apply a type constraint like where T : IDisposable when working with generic types.
  • Type must implement IAsyncDisposable (CS8410): Types used with await using must implement IAsyncDisposable or provide a suitable DisposeAsync method. If your type doesn't support asynchronous disposal, use a synchronous using statement instead or implement the required interface.
  • Mismatched disposal pattern (CS8417, CS8418): CS8417 occurs when you use await using with a type that only implements IDisposable. CS8418 occurs when you use synchronous using with a type that only implements IAsyncDisposable. Match the using keyword to the interface your type implements, or implement both interfaces if you need to support both patterns.

For more information, see Finalizers, Implement a Dispose method, and Implement a DisposeAsync method.

Using variable scope and control flow

The following compiler errors and warnings relate to incorrect usage of using variables within control flow statements:

  • CS0728: Possibly incorrect assignment to local variable which is the argument to a using or lock statement. The Dispose call or unlocking will happen on the original value of the local.
  • CS8647: A using variable cannot be used directly within a switch section (consider using braces).
  • CS8648: A goto cannot jump to a location after a using declaration.
  • CS8649: A goto cannot jump to a location before a using declaration within the same block.

Variables declared with using have specific scoping rules that prevent resource leaks. The compiler enforces these rules to ensure proper disposal.

  • Assignment to using variable (CS0728): This warning indicates you assigned a new value to a variable that's the resource in a using statement. The dispose call occurs on the original value, not the newly assigned value, which can lead to resource leaks. Initialize the resource in the using statement declaration instead of assigning to it later.

  • Using variable in switch section (CS8647): A using declaration creates a variable that's disposed at the end of its scope. When used directly in a switch section without braces, the scope is ambiguous and can lead to errors. Wrap the switch section content in braces to clearly define the scope.

  • Goto statements and using declarations (CS8648, CS8649): You can't use goto statements to jump over using declarations because jumping would skip proper resource management. CS8648 occurs when jumping forward over a using declaration, and CS8649 occurs when jumping backward to a location before a using declaration. Restructure your code to use structured control flow like loops, or move the using declaration outside the jump target.

For more information, see using statement.

Incorrect using declaration

  • CS9229: Modifiers cannot be placed on using declarations.

A variable declaration wrapped in a using declaration can't include any of the following modifiers:

  • const
  • static
  • volatile
  • readonly
  • Accessibility modifiers: public, protected, internal, private, protected internal, or private protected

The following example generates CS9229:

using System;

class Program
{
    static void Main()
    {
        // error CS9229: Modifiers cannot be placed on using declarations.
        public using var resource = new Resource();
        
        // error CS9229: Modifiers cannot be placed on using declarations.
        static using var anotherResource = new Resource();
    }
}

class Resource : IDisposable
{
    public void Dispose() { }
}

To correct this error, remove the modifier from the using declaration:

using var resource = new Resource();

For more information, see using statement.