More specifically this applies only to resources which have asynchronous dependencies themselves (but I think that's majority of them).
Concrete example:
class Foo : IAsyncDisposable { public ValueTask DisposeAsync { ... } } class Bar : IAsyncDisposable { Foo _foo; public Bar(Foo foo) { _foo = foo; // throw Exception(); } public ValueTask DisposeAsync() { return _foo.DisposeAsync(); }; } Can Bar be constructed synchronously? Let's try:
public void MakeBar(){ Foo foo; try { foo = new Foo(); return new Bar(foo); } catch { // cleanup foo. How? throw; } } We will either call foo.DisposeAsync synchronously, or we will leak resource which is not disposed. Another option is to store foo for later and call dispose in async context (that's how DI containers work), but we need to await it anyway.
My conclusion is that unless I control the object and I can guarantee that construction does not fail, the construction should be asynchronous.
Is this conclusion correct?
By asynchronous construction I mean that function which creates it returns task (or value task):
public async Task<Bar> MakeBar(){ Foo? foo = null; try { foo = new Foo(); return new Bar(foo); } catch { await foo?.DisposeAsync(); throw; } }