Как использовать неявное преобразовние при возвращении Task

Такой код не работает

Task<A> GetA()
{
    return GetB();
}

Task<B> GetB() //не мой метод, я им не владею
{
   ...
}

Нельзя неявно преобразовать тип Task<B> в тип Task<A>. При этом в типе A реализовано неявное преобразование.

class A
{   
   public static implicit operator A(B value);
}

Я написал так

Task<A> GetA()
{
    return GetB().ContinueWith<A>(b => b.Result);
}

Работает.

А как-то проще или читаемей можно это сделать?


Ответы (1 шт):

Автор решения: aepot

Есть стандартный способ оптимизации, который позволяет избавиться от лишней генерации Машины Состояний для async метода. Но он возможен при следующих условиях:

  • return await - последняя строка в методе
  • return await не находится внутри блока try или using
  • всего один await на весь метод

Тогда такой код:

private async Task DoSomethingAsync()
{
    // здесь может быть какой-то обычный синхронный код
    return await OtherMethodAsync();
}

Можно оптимизировать так

private Task DoSomethingAsync()
{
    // здесь может быть какой-то обычный синхронный код
    return OtherMethodAsync();
}

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

В вашем вопросе проблема преобразования типов, которая не относится к данному способу оптимизации, вы напутали в типах, и ожидаете что ваш implicit operator A преобразует вам не B, а Task<B>, но очевидно, что он не умеет этого делать.

Task<A> GetA() // <-- вот здесь должен быть тип Task<B>, а не Task<A>
{
    return GetB();
}

Task<B> GetB()
{
   ...
}

А снаружи, в вызывающем методе, там где A a = await GetA() уже сработает ваш implicit operator.

→ Ссылка