Skip to content

Pattern based async disposal does not work on lifted nullable structs #34701

@chsienki

Description

@chsienki

When implementing async disposal via pattern, you should be able to use a nullable version of the struct in the await using statement:

Repro:

using System;
using System.Threading;
using System.Threading.Tasks;

namespace System
{
    public interface IAsyncDisposable
    {
        ValueTask DisposeAsync();
    }
}

public class C 
{
    public static async Task M()
    {
        StructDisposer? a = null;
        await using (a) { } // DisposeAsync is not invoked
        
        StructDisposer? b = new StructDisposer();
        await using (b) { } // DisposeAsync is invoked
    }
}

public struct StructDisposer /*: IAsyncDisposable*/
{
    public async ValueTask DisposeAsync() => Console.WriteLine("DisposeAsync");
}

Expected Behaviour:

Compiles successfully.

Actual Behavior:

error CS8410: 'StructDisposer?': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable' or implement a suitable 'DisposeAsync' method.

Workaround:

Explicitly implement the IAsyncDisposable interface, and the code will compile and run successfully.

[jcouv update:] this issue is reference in the design doc. Should update the design doc when closing this issue.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions