本文介绍了可以/应任务< TResult>在C#5.0 awaitable这是协变的TResult被包裹?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我真的很喜欢用C#5.0异步编程工作。不过,也有一些地方,更新旧code是与TAP模型一致导致的问题对我来说。

下面是其中之一 - 我不知道到底为什么不TResult协变,但试图更新协接口从同步移动到异步模式时,它造成的问题对我来说:

旧code:

 公共接口IInitializable<出T> // **出通用改性剂**
{
    ///<总结>
    ///布尔值,表明如果类是准备
    ///< /总结>
    布尔将IsInitialized {搞定; }    ///<总结>
    ///例如呼叫通过电流参数初始化
    ///驱动程序初始化可以在默认的构造函数如果需要做
    ///< /总结>
    ŧ初始化();
}

新的code(不会编译):

 公共接口IAsyncInitializable<出T> // **出通用改性剂...破**
{
    ///<总结>
    ///布尔值,表明如果类是准备
    ///< /总结>
    布尔将IsInitialized {搞定; }    ///<总结>
    ///例如呼叫通过电流参数初始化
    ///驱动程序初始化可以在默认的构造函数如果需要做
    ///< /总结>
    任务<出T> InitializeAsync(); // **休息,因为任务< TResult>在TResult不变**
}

时有解决这个合理的方式,而无需修改我的API得太厉害? (奖励:为什么任务不是协变?)。有没有IAwaitable接口,但我想我可以做一个,并创建转换成一个包裹,协变,awiatable任务对象的扩展方法。还是我做错了?


解决方案

任务< T> 不能在 T被协变,因为它是一个类。只有接口和委托可以有通用的差异。

至于它是否值得做包装......我想这取决于你有多少使用您的项目中的协方差。我怀疑你会发现所有的包装和展开随着时间的推移混乱,说实话 - 如果不是的的坏只取去除协方差的打击,我会做到这一点。

I'm really enjoying working with C# 5.0 asynchronous programming. However, there are a few places where updating old code to be consistent with the TAP model is causing problems for me.

Here's one of them - I'm not sure exactly why Task<TResult> is not covariant in TResult, but it's causing problems for me when trying to update a covariant interface to move from a synchronous to an asychronous pattern:

Old code:

public interface IInitializable<out T> // ** out generic modifier **
{
    /// <summary>
    /// Boolean to indicate if class is ready
    /// </summary>
    bool IsInitialized { get; }

    /// <summary>
    /// Calls for instance to be initialized using current parameters
    /// Driver initialization can be done in the default constructor if desired
    /// </summary>
    T Initialize();
}

New code (won't compile):

public interface IAsyncInitializable<out T> // ** out generic modifier...broken **
{
    /// <summary>
    /// Boolean to indicate if class is ready
    /// </summary>
    bool IsInitialized { get; }

    /// <summary>
    /// Calls for instance to be initialized using current parameters
    /// Driver initialization can be done in the default constructor if desired
    /// </summary>
    Task<out T> InitializeAsync(); // ** breaks because Task<TResult> is invariant in TResult **
}

Is there is a reasonable way around this without modifying my APIs too drastically? (Bonus: why is Task not covariant?). There's no IAwaitable interface, but I suppose I could make one and create an extension method that converts to a wrapped, covariant, awiatable task object. Or am I doing it wrong?

解决方案

Task<T> can't be covariant in T, because it's a class. Only interfaces and delegates can have generic variance.

As for whether it's worth doing the wrapping... I guess that depends on how much you use the covariance within your project. I suspect you'll find all the wrapping and unwrapping confusing over time, to be honest - if it's not too bad to just take the hit of removing the covariance, I'd do that.

这篇关于可以/应任务&LT; TResult&GT;在C#5.0 awaitable这是协变的TResult被包裹?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-23 16:20