Подтвердить что ты не робот

Может ли/должна быть запущена задача <TResult> в С# 5.0, которая является ковариантной в TResult?

Мне очень нравится работать с асинхронным программированием С# 5.0. Тем не менее, есть несколько мест, где обновление старого кода в соответствии с моделью TAP вызывает проблемы для меня.

Здесь один из них - я точно не знаю, почему Task<TResult> не является ковариантным в TResult, но это создает проблемы для меня при попытке обновить ковариантный интерфейс для перехода от синхронного к асинхронному шаблону:

Старый код:

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();
}

Новый код (не будет компилироваться):

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<T> InitializeAsync(); // ** breaks because Task<TResult> is invariant in TResult **
}

Есть ли разумный способ обойти это без чрезмерной модификации моих API? (Бонус: почему Задача не ковариантна?). Там нет IAwaitable интерфейса, но я полагаю, что я мог бы создать его и создать метод расширения, который преобразуется в обернутый, ковариантный, awiatable объект задачи. Или я делаю это неправильно?

4b9b3361

Ответ 1

Task<T> не может быть ковариантным в T, потому что это класс. Только интерфейсы и делегаты могут иметь общую дисперсию.

Что касается того, стоит ли делать упаковку... Я думаю, это зависит от того, насколько вы используете ковариацию в своем проекте. Я подозреваю, что со временем вы обнаружите, что все обертывание и разворачивание сбивает с толку, если честно - если не так уж плохо, просто ударить по ковариации, я бы это сделал.

Ответ 2

Я считаю, что не включая поддержку компилятора для ключевого слова async на интерфейсе ITask - это серьезный надзор над частью Microsoft. К счастью, это не слишком сложно обойти это ограничение.

Я реализовал ковариантный ожидаемый интерфейс ITask<out TResult>. Его использование довольно просто.

Более подробную информацию можно найти по адресу:

https://github.com/jam40jeff/ITask