C
C#3mo ago
Stefanidze

Can i use async/await in class constructors?

I want my class constructor to send data to the database, so every instance of the class is synced with the corresponding item in the database. The problem is that database uses async, and i want to wait for the database to process the request, to output unique id, for me to use it later. Is there any way i can do that?
4 Replies
Pobiega
Pobiega3mo ago
You can't put async/await in a constructor, no. The most common way to get around this is to make the ctor private, and use a public static async Task<YourClass> Create() method
Stefanidze
Stefanidze3mo ago
ok, thanks, i will use Create method
Jimmacle
Jimmacle3mo ago
if it's something you have to await it probably shouldn't be in a constructor anyway, constructors are meant for basic object initialization and should be very fast to run
mldisibio
mldisibio3mo ago
The static factory method suggested by @Pobiega is the way to go. But there is an alternative. You can fire a Task from the constructor and then get the result using await later in a non-constructor method.
public interface IDatabase{Task<int> GetId(string name);}

public class Foo
{
readonly string _someData;
readonly Task<int> _myId;

public Foo(string someData, IDatabase db)
{
_someData = someData;
_myId = db.GetId(someData);
}

public async Task DoStuff()
{
try
{
// only retrieved once and maintained in Result property on subsequent calls (maybe use ValueTask instead)
int id = await _myId;
Console.WriteLine($"Hello {id}");
}
catch { /* handle async error! */ }
}
}
public interface IDatabase{Task<int> GetId(string name);}

public class Foo
{
readonly string _someData;
readonly Task<int> _myId;

public Foo(string someData, IDatabase db)
{
_someData = someData;
_myId = db.GetId(someData);
}

public async Task DoStuff()
{
try
{
// only retrieved once and maintained in Result property on subsequent calls (maybe use ValueTask instead)
int id = await _myId;
Console.WriteLine($"Hello {id}");
}
catch { /* handle async error! */ }
}
}