Mar*_*eal 262 c# constructor async-await
我有一个Silverlight项目,我试图在构造函数中填充一些数据:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,我收到一个错误:
修饰符
async对此项目无效
当然,如果我在标准方法中包装并从构造函数中调用它:
public async void Foo()
{
Data = await GetDataTask();
}
Run Code Online (Sandbox Code Playgroud)
它工作正常.同样,如果我使用旧的由内而外的方式
GetData().ContinueWith(t => Data = t.Result);
Run Code Online (Sandbox Code Playgroud)
这也有效.我只是想知道为什么我们不能await直接在构造函数内调用.可能有很多(甚至是明显的)边缘情况和反对它的理由,我只是想不出来.我也在寻找解释,但似乎找不到任何解释.
Pie*_*off 214
由于无法创建异步构造函数,因此我使用静态异步方法返回由私有构造函数创建的类实例.这不是很优雅,但它可以正常工作.
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;
}
}
Run Code Online (Sandbox Code Playgroud)
svi*_*ick 194
构造函数与返回构造类型的方法非常相似.并且async方法不能返回任何类型,它必须是"火与忘记" void,或者Task.
如果类型的构造函数T实际返回Task<T>,那将是非常混乱,我想.
如果异步构造函数的行为方式与async void方法相同,则会破坏构造函数的含义.构造函数返回后,您应该获得一个完全初始化的对象.不是将来在某个未定义的点上实际正确初始化的对象.也就是说,如果你很幸运,异步初始化不会失败.
这一切只是猜测.但在我看来,有一个异步构造函数的可能性会带来更多的麻烦而不是它的价值.
如果你真的想要方法的"即发即忘"语义async void(如果可能的话应该避免),你可以轻松地将所有代码封装在一个async void方法中,并从你的构造函数中调用它,正如你在问题中提到的那样.
Har*_*lse 48
您的问题与创建文件对象和打开文件相当.事实上,在实际使用对象之前,有许多类需要执行两个步骤:create + Initialize(通常称为Open类似的东西).
这样做的好处是构造函数可以是轻量级的.如果需要,您可以在实际初始化对象之前更改某些属性.设置所有属性后,将调用Initialize/ Open函数以准备要使用的对象.此Initialize功能可以是异步的.
缺点是你必须相信Initialize()他所使用的课程的用户,在他使用你班级的任何其他功能之前.事实上,如果你想让你的课程充分证明(傻瓜证明?),你必须检查Initialize()所调用的每个函数.
使这更容易的模式是将构造函数声明为private并创建一个公共静态函数,该函数将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
}
Run Code Online (Sandbox Code Playgroud)
用法如下:
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);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
131932 次 |
| 最近记录: |