Согласен, блог Диксин фантастический
из менее обсуждаемых возможностей C # 7 - это «обобщенные типы асинхронного возврата», которые Microsoft описывает как:
Возврат объекта Task из асинхронных методов может привести к появлению узких мест производительности в определенных путях. Задача является ссылочным типом, поэтому его использование означает выделение объекта. В случаях, когда метод, объявленный с модификатором async, возвращает кэшированный результат или завершается синхронно, дополнительные выделения могут стать значительными временными затратами в критически важных для кода разделах кода. Это может стать очень дорогостоящим, если эти распределения происходят в тесных циклах.
Новая функция языка означает, что асинхронные методы могут возвращать другие типы в дополнение кTask
, Task<T>
а такжеvoid
, Возвращаемый тип должен по-прежнему удовлетворять асинхронному шаблону, то есть метод GetAwaiter должен быть доступен. В качестве одного конкретного примера, тип ValueTask был добавлен в .NET Framework для использования этой новой языковой функции:
Это звучит замечательно, но я не могу на всю жизнь найти ни одного примера, который бы не использовал акцииValueTask<T>
тип. Я хочу сделать свой собственный тип, похожий на задачу. В частности, я хочу тип, который ведет себя какTask<T>
, но с более функциональным стилем обработки ошибок.
Вот тип, который я использую для функциональной обработки ошибок в моем проекте:
public class Try<T> {
public T Data { get; }
public Exception Error { get; }
public bool HasData => Error == null;
public bool HasError => Error != null;
public Try(T data) {
Data = data;
}
public Try(Exception error) {
Error = error;
}
}
Вот что я думаю должен выглядеть мой пользовательский ожидаемый тип:
public class TryTask<T> : Task<Try<T>> {
public TryTask(Func<Try<T>> func)
: base(func) { }
//GetAwaiter is defined on base type, so we should be okay there
}
Это все компилируется, пока я не попытаюсь использовать его как тип асинхронного возврата:
async TryTask<int> DoWhatever() {
return await new TryTask<int>(() => new Try<int>(1));
}
Этот метод выдаст ошибку компилятораТип возвращаемого значения асинхронного метода должен быть void, Task или Task.
Как мне сделать это или что-то вроде этого скомпилировать?
Обновить:
Чтобы подтвердить, я использую версию VS 2017 от 3/7, и я могу использовать другие функции C # 7 в моем проекте, такие как локальные функции.
Я также пытался использоватьValueTask
и я получаю ту же ошибку компилятора.
static async ValueTask<int> DoWhatever() {
return await new ValueTask<int&,gt;(1);
}
Вот еще один пост, который проливает свет на то, что происходит.
Как мне получить новую асинхронную семантику, работающую в VS2017 RC?
По-видимому, необходимо определить отдельный тип «построителя метода» и применить специальные атрибуты к ожидаемому типу. Я не знаю, действительно ли у меня есть время копаться в этом. Это больше похоже на хакерство метапрограммирования, чем на «язык».