ValueTask<T>
це не підмножина Task<T>
, це суперсет .
ValueTask<T>
є дискримінаційним об'єднанням T і a Task<T>
, що робить його без розподілу для ReadAsync<T>
синхронного повернення доступного йому значення T (на відміну від використання Task.FromResult<T>
, якому потрібно виділити Task<T>
екземпляр). ValueTask<T>
є очікуваним, тому більшість споживання екземплярів буде невідрізним від типу "a" Task<T>
.
ValueTask, будучи структурою, дозволяє записувати методи асинхронізації, які не виділяють пам'ять, коли вони працюють синхронно, не порушуючи послідовності API. Уявіть, що є інтерфейс із методом повернення задач. Кожен клас, що реалізує цей інтерфейс, повинен повернути завдання, навіть якщо вони трапляються синхронно (сподіваємось, використовуючи Task.FromResult). Звичайно, в інтерфейсі можуть бути два різних способу, синхронний та асинхронний, але для цього потрібно 2 різних реалізації, щоб уникнути "синхронізації через асинхронізацію" та "асинхронізації через синхронізацію".
Таким чином, ви можете написати один метод, який є або асинхронним, або синхронним, а не записати один ідентичний метод для кожного. Ви можете використовувати його де завгодно, Task<T>
але це часто нічого не додає.
Що ж, це додає одне: воно додає передбачуване обіцянку абоненту, що метод насправді використовує додаткову функціональність, яку ValueTask<T>
надає. Я особисто віддаю перевагу вибору параметрів та типів повернення, які максимально повідомляють абоненту. Не повертайтеся, IList<T>
якщо перерахування не може забезпечити підрахунок; не повертайся, IEnumerable<T>
якщо може. Ваші споживачі не повинні шукати будь-яку документацію, щоб знати, який із ваших методів можна розумно назвати синхронним, а який - не.
Не бачу майбутніх змін дизайну як переконливого аргументу. Зовсім навпаки: якщо метод змінює свою семантику, він повинен порушити збірку, поки всі виклики до нього не будуть оновлені відповідно. Якщо це вважається небажаним (і повірте, я співчуваю бажанням не порушувати збірку), розгляньте версію інтерфейсу.
Це, по суті, те, для чого сильне введення тексту.
Якщо хтось із програмістів, які розробляють методи асинхронізації у вашому магазині, не можуть прийняти обґрунтованих рішень, може бути корисним призначити старшого наставника кожному з тих менш досвідчених програмістів і провести щотижневий огляд коду. Якщо вони здогадуються неправильно, поясніть, чому це слід робити інакше. Це накладні витрати для старших хлопців, але це призведе юніорів до швидкості набагато швидше, ніж просто кинути їх у глибокий кінець і дати їм якесь довільне правило, яке вони повинні виконувати.
Якщо хлопець, який написав метод, не знає, чи можна його називати синхронно, хто це на Землі ?!
Якщо у вас так багато недосвідчених програмістів, які пишуть методи асинхронізації, називають їх ті ж люди? Чи кваліфіковані вони самі, щоб зрозуміти, які з них можна безпечно називати асинхронією, чи вони почнуть застосовувати аналогічно довільне правило до того, як називають ці речі?
Проблема тут не у тому, що ти повертаєшся, а програмісти ставлять у ролі, до яких вони не готові. Це, мабуть, сталося з причини, тому я впевнений, що це неможливо виправдати. Опис його, безумовно, не є рішенням. Але пошук способу проникнути проблеми повз компілятор також не є рішенням.
ValueTask<T>
(з точки зору розподілів), які не реалізуються для операцій, які насправді є асинхронними (тому що в такому випадкуValueTask<T>
все ще знадобиться розподіл купи). Є також питання проTask<T>
те, що у бібліотеках є багато іншої підтримки.