我有一个项目,我正在尝试在构造函数中填充一些数据:
public class ViewModel
{
public ObservableCollection<TData> Data { get; set; }
async public ViewModel()
{
Data = await GetDataTask();
}
public Task<ObservableCollection<TData>> GetDataTask()
{
Task<ObservableCollection<TData>> task;
//Create a task which represents getting the data
return task;
}
}
不幸的是,我收到一个错误:
修饰符对此项目无效
async
当然,如果我包装一个标准方法并从构造函数调用它:
public async void Foo()
{
Data = await GetDataTask();
}
它工作正常。同样,如果我使用旧的由内而外的方式
GetData().ContinueWith(t => Data = t.Result);
那也行得通。我只是想知道为什么我们不能直接从构造函数中调用。可能有很多(甚至是明显的)边缘情况和反对它的原因,我想不出任何。我也四处寻找解释,但似乎找不到任何解释。await
由于无法创建异步构造函数,因此我使用静态异步方法返回由私有构造函数创建的类实例。这并不优雅,但工作正常。
public class ViewModel
{
public ObservableCollection<TData> Data { get; set; }
//static async method that behave like a constructor
async public static Task<ViewModel> BuildViewModelAsync()
{
ObservableCollection<TData> tmpData = await GetDataTask();
return new ViewModel(tmpData);
}
// private constructor called by the async method
private ViewModel(ObservableCollection<TData> Data)
{
this.Data = Data;
}
}
构造函数的作用与返回构造类型的方法非常相似。并且方法不能返回任何类型,它必须是“即发即弃”,或者.async
void
Task
如果类型的构造函数实际上返回,那将非常令人困惑,我认为。T
Task<T>
如果异步构造函数的行为方式与方法相同,则会破坏构造函数的本意。构造函数返回后,您应该得到一个完全初始化的对象。不是将来某个未定义点实际正确初始化的对象。也就是说,如果你很幸运并且异步初始化没有失败。async void
这一切都只是一个猜测。但在我看来,拥有异步构造函数的可能性会带来比它的价值更多的麻烦。
如果你真的想要方法的“即发即弃”语义(如果可能的话,应该避免),你可以轻松地将所有代码封装在一个方法中,并从你的构造函数调用它,正如你在问题中提到的。async void
async void
您的问题相当于创建文件对象并打开文件。实际上,在实际使用该对象之前,您必须执行许多类的两个步骤:create + Initialize(通常称为类似于Open的东西)。
这样做的优点是构造函数可以是轻量级的。如果需要,可以在实际初始化对象之前更改某些属性。设置所有属性后,将调用 / 函数来准备要使用的对象。此函数可以是异步的。Initialize
Open
Initialize
缺点是,在使用类的任何其他函数之前,您必须信任类的用户,该用户将调用该用户。事实上,如果你想让你的类完全证明(万无一失?),你必须签入每个被调用的函数。Initialize()
Initialize()
使这更容易的模式是声明构造函数私有并创建一个公共静态函数,该函数将在返回构造对象之前构造对象并调用。这样,您就会知道有权访问该对象的每个人都使用了该函数。Initialize()
Initialize
该示例演示了一个类,该类模拟所需的异步构造函数
public MyClass
{
public static async Task<MyClass> CreateAsync(...)
{
MyClass x = new MyClass();
await x.InitializeAsync(...)
return x;
}
// make sure no one but the Create function can call the constructor:
private MyClass(){}
private async Task InitializeAsync(...)
{
// do the async things you wanted to do in your async constructor
}
public async Task<int> OtherFunctionAsync(int a, int b)
{
return await ... // return something useful
}
用法如下:
public async Task<int> SomethingAsync()
{
// Create and initialize a MyClass object
MyClass myObject = await MyClass.CreateAsync(...);
// use the created object:
return await myObject.OtherFunctionAsync(4, 7);
}
模板简介:该模板名称为【 C#构造函数可以是异步的吗?】,大小是暂无信息,文档格式为.编程语言,推荐使用Sublime/Dreamweaver/HBuilder打开,作品中的图片,文字等数据均可修改,图片请在作品中选中图片替换即可,文字修改直接点击文字修改即可,您也可以新增或修改作品中的内容,该模板来自用户分享,如有侵权行为请联系网站客服处理。欢迎来懒人模板【C#】栏目查找您需要的精美模板。