ValueTask<T>
bukan bagian dari Task<T>
, itu superset .
ValueTask<T>
adalah penyatuan terdiskriminasi dari T dan a Task<T>
, membuatnya bebas alokasi untuk ReadAsync<T>
mengembalikan nilai T yang tersedia secara sinkron (berbeda dengan menggunakan Task.FromResult<T>
, yang perlu mengalokasikan Task<T>
instance). ValueTask<T>
dapat ditunggu, sehingga sebagian besar konsumsi instance tidak dapat dibedakan dengan Task<T>
.
ValueTask, sebagai sebuah struct, memungkinkan penulisan metode async yang tidak mengalokasikan memori ketika mereka berjalan secara sinkron tanpa mengurangi konsistensi API. Bayangkan memiliki antarmuka dengan metode pengembalian tugas. Setiap kelas yang mengimplementasikan antarmuka ini harus mengembalikan Tugas bahkan jika mereka mengeksekusi secara bersamaan (mudah-mudahan menggunakan Task.FromResult). Anda tentu saja dapat memiliki 2 metode yang berbeda pada antarmuka, yang sinkron dan async tetapi ini membutuhkan 2 implementasi yang berbeda untuk menghindari "sinkronisasi lebih dari async" dan "async atas sinkronisasi".
Jadi itu memungkinkan Anda menulis satu metode yang asinkron atau sinkron, daripada menulis satu metode yang identik untuk masing-masing. Anda bisa menggunakannya di mana saja Anda gunakan Task<T>
tetapi seringkali tidak akan menambahkan apa pun.
Yah, itu menambahkan satu hal: Ini menambahkan janji tersirat kepada pemanggil bahwa metode ini benar-benar menggunakan fungsionalitas tambahan yang ValueTask<T>
menyediakan. Saya pribadi lebih suka memilih parameter dan mengembalikan tipe yang memberi tahu penelepon sebanyak mungkin. Jangan kembali IList<T>
jika enumerasi tidak dapat memberikan hitungan; jangan kembali IEnumerable<T>
jika itu bisa. Konsumen Anda seharusnya tidak perlu mencari dokumentasi apa pun untuk mengetahui metode mana yang dapat disebut secara serempak dan mana yang tidak.
Saya tidak melihat perubahan desain di masa depan sebagai argumen yang meyakinkan di sana. Justru sebaliknya: Jika suatu metode mengubah semantiknya, itu harus memecah bangunan sampai semua panggilan ke itu diperbarui sesuai. Jika itu dianggap tidak diinginkan (dan percayalah, saya bersimpati pada keinginan untuk tidak merusak build), pertimbangkan versi antarmuka.
Ini pada dasarnya adalah tujuan dari pengetikan yang kuat.
Jika beberapa pemrogram yang merancang metode async di toko Anda tidak dapat membuat keputusan berdasarkan informasi, mungkin akan membantu jika menugaskan mentor senior untuk masing-masing pemrogram yang kurang berpengalaman dan melakukan peninjauan kode mingguan. Jika mereka salah menebak, jelaskan mengapa itu harus dilakukan secara berbeda. Ini overhead untuk orang-orang senior, tapi itu akan membuat junior lebih cepat lebih cepat daripada hanya melemparkan mereka di ujung yang dalam dan memberi mereka beberapa aturan sewenang-wenang untuk diikuti.
Jika orang yang menulis metode itu tidak tahu apakah itu bisa disebut secara serempak, siapa di Bumi yang melakukannya ?!
Jika Anda memiliki banyak programmer yang tidak berpengalaman yang menulis metode async, apakah mereka juga memanggil mereka? Apakah mereka memenuhi syarat untuk mencari tahu sendiri mana yang aman untuk disebut async, atau akankah mereka mulai menerapkan aturan arbitrer yang serupa dengan cara mereka menyebut hal-hal ini?
Masalahnya di sini bukan tipe pengembalian Anda, itu adalah programer yang dimasukkan ke dalam peran yang belum siap. Itu pasti terjadi karena suatu alasan, jadi saya yakin itu tidak mudah untuk diperbaiki. Menggambarkannya tentu bukan solusi. Tetapi mencari cara untuk menyelinap masalah melewati kompiler juga bukan solusi.
ValueTask<T>
(dalam hal alokasi) tidak terwujud untuk operasi yang sebenarnya tidak sinkron (karena dalam kasusValueTask<T>
itu masih perlu alokasi tumpukan). Ada juga masalahTask<T>
memiliki banyak dukungan lain di perpustakaan.