可以/应该将任务包装在C#5.0中,等待TResult中的协变吗?
我非常喜欢使用C#5.0异步编程。 但是,有些地方更新旧代码以与TAP模型保持一致会给我带来问题。
这是其中之一 – 我不确定为什么Task
在TResult中不协变,但在尝试更新协变接口以从同步模式转换为异步模式时,它会给我带来问题:
旧代码:
public interface IInitializable // ** out generic modifier ** { /// /// Boolean to indicate if class is ready /// bool IsInitialized { get; } /// /// Calls for instance to be initialized using current parameters /// Driver initialization can be done in the default constructor if desired /// T Initialize(); }
新代码(不会编译):
public interface IAsyncInitializable // ** out generic modifier...broken ** { /// /// Boolean to indicate if class is ready /// bool IsInitialized { get; } /// /// Calls for instance to be initialized using current parameters /// Driver initialization can be done in the default constructor if desired /// Task InitializeAsync(); // ** breaks because Task is invariant in TResult ** }
有没有一种合理的方法来解决这个问题而不是过于严格地修改我的API? (加分:为什么Task不协变?)。 没有IAwaitable接口,但我想我可以制作一个并创建一个扩展方法,转换为一个包装的,协变的,可用的任务对象。 或者我做错了吗?
Task
在T
不能协变,因为它是一个类。 只有接口和委托可以具有generics差异。
至于是否值得做包装……我想这取决于你在项目中使用协方差的程度。 我怀疑你会发现随着时间的推移会让所有的包装和展开混乱,说实话 – 如果只是采取消除协方差的命中并不是太糟糕,我会这样做。
我相信不包括编译器对ITask接口上的async关键字的支持是微软的一个主要疏忽。 幸运的是,解决这个限制并不太难。
我已经实现了一个协变的等待ITask
接口。 它的用法非常简单。
更多信息可在以下url找到: