Apakah penggunaan sufiks "Async" dalam nama metode bergantung pada apakah pengubah 'asinkron' digunakan?

107

Apa konvensi untuk nama metode sufiks dengan "Async"?

Haruskah sufiks "Async" ditambahkan hanya ke metode yang dideklarasikan dengan asyncpengubah?

public async Task<bool> ConnectAsync()

Atau apakah cukup metode ini kembali Task<T>atau Task?

public Task<bool> ConnectAsync()
kasperhj
sumber
4
Untuk bagian penamaan, dokumen TAP mengatakan: Metode asinkron di TAP menyertakan sufiks Async setelah nama operasi; misalnya, GetAsync untuk operasi get. Jika Anda menambahkan metode TAP ke kelas yang sudah berisi nama metode tersebut dengan sufiks Async, gunakan sufiks TaskAsync sebagai gantinya. Misalnya, jika kelas sudah memiliki metode GetAsync, gunakan nama GetTaskAsync.
James Manning
4
oke, saya rasa saya bingung dengan judul pertanyaan "Konvensi penamaan untuk metode asinkron"
James Manning
1
Ini adalah pertanyaan yang dibangun dengan buruk. Orang-orang bertengkar, jawaban samar-samar.
Luke Puplett
4
Karena banyak orang telah salah paham dan memperdebatkan hal yang sebenarnya ditanyakan, bertanya-tanya apakah itu pertanyaan dua bagian, dll. Bukti yang membingungkan adalah bahwa orang-orang bingung.
Luke Puplett
2
@DavidRR Sampai hari ini saya masih tidak memahami jumlah kebingungan yang tampaknya disebabkan oleh pertanyaan ini. Jika hasil edit Anda menimbulkan kebingungan sehingga telah membantu Anda dan mungkin dapat membantu orang lain, maka saya menyambut baik suntingan Anda karena Anda telah mencapai sesuatu yang tidak dapat saya lakukan dalam formulasi aslinya. Pertanyaannya sekarang sudah sangat tua sekarang sehingga saya hampir tidak dapat mengingat pola pikir saya ketika saya menanyakannya di sini dan maksud aslinya kurang penting. Jawaban Luke mencerminkan bahwa tidak semua bingung. Saya merasa sangat membantu.
kasperhj

Jawaban:

128

Saya pikir kebenarannya ambigu bahkan dari dokumentasi Microsoft:

Dalam Visual Studio 2012 dan .NET Framework 4.5, metode apa pun yang dikaitkan dengan asynckata kunci ( Asyncdalam Visual Basic) dianggap sebagai metode asinkron, dan kompiler C # dan Visual Basic melakukan transformasi yang diperlukan untuk menerapkan metode secara asinkron dengan menggunakan TAP. Metode asynchronous harus mengembalikan sebuah Taskatau sebuah Task<TResult>objek.

http://msdn.microsoft.com/en-us/library/hh873177(v=vs.110).aspx

Itu belum benar. Metode apa pun dengan asyncasinkron dan kemudian mengatakannya harus mengembalikan a Taskatau Task<T>- yang tidak tepat untuk metode di bagian atas tumpukan panggilan, Button_Click misalnya, atau async void.

Tentu, Anda harus mempertimbangkan apa gunanya kebaktian itu?

Anda dapat mengatakan bahwa Asynckonvensi sufiks adalah untuk menyampaikan kepada pengguna API bahwa metode tersebut dapat menunggu. Agar metode dapat menunggu, ia harus mengembalikan Taskuntuk void, atau Task<T>untuk metode pengembalian nilai, yang berarti hanya yang terakhir yang dapat di-sufiks Async.

Atau Anda mungkin mengatakan bahwa file Async konvensi sufiks adalah untuk mengomunikasikan bahwa metode dapat segera kembali, melepaskan utas saat ini untuk melakukan pekerjaan lain dan berpotensi menyebabkan balapan.

Kutipan dokumen Microsoft ini mengatakan:

Berdasarkan konvensi, Anda menambahkan "Asinkron" ke nama metode yang memiliki pengubah Asinkron atau asinkron.

http://msdn.microsoft.com/en-us/library/hh191443.aspx#BKMK_NamingConvention

Yang bahkan tidak menyebutkan bahwa metode asynchronous Anda sendiri yang kembali Taskmembutuhkan Asyncsufiks, yang menurut saya kita semua setuju.


Jadi jawaban atas pertanyaan ini bisa jadi: keduanya. Dalam kedua kasus, Anda perlu menambahkan Asyncmetode dengan asynckata kunci dan pengembalian Taskatau Task<T>.


Saya akan meminta Stephen Toub untuk mengklarifikasi situasinya.

Memperbarui

Jadi saya lakukan. Dan inilah yang ditulis orang baik kita:

Jika metode publik adalah Pengembalian tugas dan bersifat asinkron (berbeda dengan metode yang diketahui selalu mengeksekusi secara sinkron hingga selesai tetapi masih mengembalikan Tugas karena beberapa alasan), metode tersebut harus memiliki akhiran "Asinkron". Itu pedomannya. Sasaran utama di sini dengan penamaan adalah untuk membuatnya sangat jelas bagi konsumen tentang fungsionalitas bahwa metode yang dipanggil kemungkinan besar tidak akan menyelesaikan semua pekerjaannya secara sinkron; ini tentu saja juga membantu dalam kasus di mana fungsionalitas diekspos dengan metode sinkron dan asinkron sehingga Anda memerlukan perbedaan nama untuk membedakannya. Bagaimana metode mencapai implementasi asynchronousnya tidak penting untuk penamaan: apakah async / await digunakan untuk mengumpulkan bantuan compiler, atau apakah jenis dan metode dari System.Threading.Tasks digunakan secara langsung (e. g. TaskCompletionSource) tidak terlalu penting, karena itu tidak mempengaruhi tanda tangan metode sejauh menyangkut konsumen metode.

Tentu saja, selalu ada pengecualian pada pedoman. Yang paling menonjol dalam kasus penamaan adalah kasus di mana alasan keseluruhan tipe adalah untuk menyediakan fungsionalitas yang berfokus pada asinkron, dalam hal ini memiliki Asinkron pada setiap metode akan berlebihan, misalnya metode pada Tugas itu sendiri yang menghasilkan Tugas lain .

Sedangkan untuk metode asynchronous void-return, tidak diinginkan untuk memiliki metode tersebut di area permukaan publik, karena pemanggil tidak memiliki cara yang baik untuk mengetahui kapan pekerjaan asinkron telah selesai. Jika Anda harus mengekspos metode asinkron yang kembali kosong secara publik, Anda mungkin ingin memiliki nama yang menyatakan bahwa pekerjaan asinkron sedang dimulai, dan Anda dapat menggunakan akhiran "Asinkron" di sini jika memungkinkan. Mengingat betapa jarangnya kasus ini, saya berpendapat ini benar-benar jenis keputusan kasus per kasus.

Saya harap itu membantu, Steve

Panduan singkat dari kalimat pembuka Stephen cukup jelas. Ini mengecualikan async voidkarena tidak biasa ingin membuat API publik dengan desain seperti itu karena cara yang benar untuk mengimplementasikan void asinkron adalah dengan mengembalikan Taskinstance biasa dan membiarkan compiler melakukan sihirnya. Namun, jika Anda memang menginginkan public async void, maka Asyncdisarankan untuk menambahkan . async voidMetode top-of-stack lainnya seperti event handler biasanya tidak bersifat publik dan tidak penting / memenuhi syarat.

Bagi saya, ini memberi tahu saya bahwa jika saya bertanya-tanya tentang sufiks Asyncpada an async void, saya mungkin harus mengubahnya menjadi an async Tasksehingga penelepon dapat menunggunya, lalu tambahkan Async.

Luke Puplett
sumber
20
Sayang sekali kami tidak memiliki pemeriksaan waktu kompilasi untuk pemanggilan metode .. oh tunggu. Jika saya menamai Metode Get atau GetAsync dan tidak menggunakan await dari sisi pemanggil, kompilasi akan gagal dibangun. Jadi, konvensi ini SILLY dan benar-benar bertentangan dengan banyak pedoman Microsoft Style, seperti menghindari hal-hal seperti PersonStringatau PriceDecimalmengapa menggunakan GetAsync- konsumen API dari async API tidak perlu khawatir tentang ini karena permintaan selalu kembali setelah semua tugas selesai. Itu konyol dan sangat mengganggu saya. Tapi itu hanyalah konvensi lain yang tidak ada yang benar-benar tahu mengapa itu ada di sana.
Piotr Kula
2
@ppumkin: Seperti yang ditunjukkan Stephen, sebuah metode dapat dengan mudah menjadi asinkron tanpa menggunakan async / await, sehingga pemanggil tidak memiliki indikasi apa pun selain nama apakah fungsionalitas tersebut berjalan asinkron atau tidak.
Hannobo
6
@ppumkin: Gagal menunggu metode async, secara default, menghasilkan peringatan waktu kompilasi; bukan kesalahan versi.
Dustin Cleveland
7
Menurut saya konvensi ini konyol. Ada tiga indikasi otomatis bahwa suatu metode asinkron: 1. Jenis kembaliannya adalah Task. 2. Penyelesaian kode menampilkan petunjuk yang bisa ditunggu 3. IDE akan memperingatkan Anda dengan menggarisbawahi warna hijau dan menampilkan peringatan compiler. Jadi saya setuju dengan @ppumkin. Async-suffix sama konyolnya jika Anda menulis properti seperti ini: public Lazy <Customer> CustomerLazy. Siapa yang akan melakukan ini! ??
Marco
2
@Marco Saya mengemukakan ide ini di GitHub, menurut saya itu adalah tempat terbaik, tetapi tidak memiliki keterlibatan dengannya, saya pikir saya akan mendapatkannya: github.com/dotnet/core/issues/1464
Luke Puplett
68

Saya membangun banyak layanan API dan aplikasi lain yang memanggil sistem lain di mana sebagian besar kode saya berjalan asinkron.

Aturan praktis saya sendiri yang saya ikuti adalah:

Jika ada metode non-async dan async yang mengembalikan hal yang sama, saya sufiks metode asinkron dengan Async. Jika tidak, tidak.

Contoh:

Hanya satu metode:

public async Task<User> GetUser() { [...] }

Metode yang sama dengan dua tanda tangan:

public User GetUser() { [...] }

public async Task<User> GetUserAsync() { [...] }

Ini masuk akal karena ini adalah data yang sama yang dikembalikan tetapi satu-satunya hal yang berbeda adalah cara mengembalikan data , bukan datanya sendiri.

Saya juga berpikir konvensi penamaan ini ada karena kebutuhan untuk memperkenalkan metode asinkron dan tetap mempertahankan kompatibilitas ke belakang.

Saya berpendapat bahwa kode baru tidak boleh menggunakan sufiks Async. Ini sama jelasnya dengan tipe kembalian dari String, atau Int seperti yang disebutkan sebelumnya di utas ini.

Jonas Stensved
sumber
8
Saya setuju, terutama bahwa biasanya Anda perlu menggunakan 'asinkron sepanjang jalan', dalam hal ini sufiksnya berlebihan - apa gunanya menambahkannya ke 90% kode;)
Bartosz
3
inilah solusi terbaik. Tanpa menyadarinya, saya telah melakukan cara yang sama di API saya.
Marco
2
Ini jauh lebih baik daripada memberi akhiran dengan "Async" semua metode aplikasi asinkron
Mariusz Jamro
Masalah dengan teknik ini adalah jika Anda membuat versi non-asinkron nanti, Anda tidak dapat menggunakan nama "GetUser ()" yang Anda sukai.
David
3
Ini adalah cara pragmatis untuk pergi. Menambahkan Async ke setiap metode yang memiliki pengubah asinkron hanyalah Hungarian Notation 2019. @David jika Anda akhirnya menambahkan versi non-asinkron nanti, ganti nama metode dan ikuti konvensi penamaan atau jangan lakukan itu.
Skrymsli
25

Apa konvensi untuk nama metode sufiks dengan "Async"?

The Pola Asynchronous berbasis Tugas (TAP) perintah bahwa metode harus selalu mengembalikan Task<T>(atau Task) dan diberi nama dengan async akhiran; ini terpisah dari penggunaan async. Keduanya Task<bool> Connect()dan akan mengkompilasi dan berjalan dengan baik, tetapi Anda tidak akan mengikuti konvensi penamaan TAP.asyncTask<bool> Connect()

Haruskah metode berisi asyncpengubah, atau cukup sehingga hanya mengembalikan Tugas?

Jika tubuh metode (terlepas dari jenis atau nama yang dikembalikan) termasuk await, Anda harus menggunakan async; dan kompilator akan memberi tahu Anda "Operator 'await' hanya dapat digunakan di dalam metode async. ...". Kembali Task<T>atau Tasktidak "cukup" untuk menghindari penggunaan async. Lihat async (C # Reference) untuk detailnya.

Yaitu yang mana dari tanda tangan ini yang benar:

Kedua dan benar mengikuti konvensi TAP. Anda selalu dapat menggunakan kata kunci, tetapi Anda akan mendapatkan peringatan compiler "Metode async ini tidak memiliki operator 'await' dan akan berjalan secara sinkron. ..." jika body tidak digunakan .asyncTask<bool> ConnectAsync()Task<bool> ConnectAsync()asyncawait

Ðаn
sumber
1
Dia mengacu pada apakah Anda menambahkan "Async" ke nama metode atau tidak, bukan apakah Anda menggunakan asynckata kunci.
Pelayanan
1
@Servy apakah menggunakan kata kunci atau tidak asyncadalah bagian kedua dari pertanyaan.
Corak
2
@ Servy Ini adalah pertanyaan dua bagian. Bagian pertama, seperti yang Anda katakan adalah apakah akan menambahkan "Async" ke nama metode atau tidak. Bagian kedua adalah apakah akan menggunakan asyncpengubah atau tidak . Lihat juga contoh OP, public async Task<bool> ConnectAsync()(dengan asyncpengubah) vs public Task<bool> ConnectAsync()(tanpa asyncpengubah). Metode nama itu sendiri memiliki akhiran "async" dalam kedua kasus.
Corak
2
Ini bukan pertanyaan dua bagian. Pertanyaannya adalah, haruskah "Async" ditambahkan ke nama metode dari metode yang dikembalikan Taskatau metode yang dimiliki async Task.
kasperhj
3
@lejon: Anda harus meningkatkan pertanyaan; "vs." potongan kode memperjelas pertanyaan (secara keseluruhan) tentang asinkron karena itulah satu-satunya perbedaan.
Ðаn
11

atau cukup hanya mengembalikan Task?

Bahwa. Kata asynckunci bukanlah masalah sebenarnya di sini. Jika Anda mengimplementasikan asynchrony tanpa menggunakan asynckata kunci, metodenya masih "Async", dalam pengertian umum.

Pelayanan
sumber
7

Karena Taskdan Task<T>keduanya merupakan tipe yang bisa ditunggu, mereka mewakili beberapa operasi asinkron. Atau setidaknya mereka harus mewakili.

Anda harus menambahkan sufiks Asyncke metode yang, dalam beberapa kasus (tidak harus semua), tidak mengembalikan nilai melainkan mengembalikan pembungkus di sekitar operasi yang sedang berlangsung. Pembungkus itu biasanya a Task, tetapi pada Windows RT bisa IAsyncInfo. Ikuti firasat Anda dan ingat bahwa jika pengguna kode Anda melihat Asyncfungsinya, dia akan tahu bahwa pemanggilan metode itu dipisahkan dari hasil metode itu dan mereka perlu bertindak sesuai dengan itu.

Perhatikan bahwa ada metode seperti Task.Delaydan Task.WhenAllyang mengembalikan Tasknamun tidak memiliki Asyncsufiks.

Perhatikan juga bahwa ada async voidmetode yang mewakili api dan lupakan metode asinkron dan Anda harus lebih berhati-hati bahwa metode tersebut dibangun dengan cara seperti itu.

Toni Petrina
sumber
6

Saya berpendapat bahwa itu harus menggunakan Async-suffix jika mengembalikan Tugas terlepas dari apakah metode tersebut dideklarasikan dengan asyncpengubah atau tidak.

Alasan di baliknya adalah bahwa nama tersebut dideklarasikan di antarmuka. Antarmuka mendeklarasikan tipe kembalian yaitu aTask . Kemudian ada dua implementasi dari antarmuka itu, satu implementasi mengimplementasikannya menggunakan asyncpengubah, yang lainnya tidak.

public interface IFoo
{
    Task FooAsync();
}

public class FooA : IFoo
{
    public Task FooAsync() { /* ... */ }
}

public class FooB : IFoo
{
    public async Task FooAsync() { /* ... */ }
}
Fred
sumber
Ini sangat benar. Kami selalu menggunakan antarmuka, di mana saja, dan antarmuka tidak dapat dinyatakan sebagai asinkron. Jadi panduan resmi tentang penggunaan sufiks Async tampaknya benar-benar tidak masuk akal bagi saya. Saya pikir kata kunci async hanyalah detail implementasi, bagian dari internal metode, dan tidak boleh memengaruhi namanya atau eksternal apa pun.
Al Kepp
5

Dalam Pemrograman Asinkron dengan async dan menunggu (C #) , Microsoft menawarkan panduan berikut:

Konvensi penamaan

Berdasarkan konvensi, Anda menambahkan "Async" ke nama metode yang memiliki pengubah asinkron .

Anda dapat mengabaikan konvensi di mana acara, kelas dasar, atau kontrak antarmuka menyarankan nama yang berbeda. Misalnya, Anda tidak boleh mengganti nama penangan kejadian umum, sepertiButton1_Click .

Saya menemukan panduan ini tidak lengkap dan tidak memuaskan. Apakah ini berarti bahwa jika asyncpengubah tidak ada, metode ini harus dinamai, Connectbukan ConnectAsync?

public Task<bool> ConnectAsync()
{
    return ConnectAsyncInternal();
}

Saya kira tidak. Seperti yang ditunjukkan dalam jawaban singkat oleh @Servy dan jawaban yang lebih rinci oleh @Luke Puplett , saya percaya bahwa itu tepat dan memang diharapkan metode ini harus dinamai ConnectAsync(karena mengembalikan sebuah menunggu). Untuk mendukung lebih lanjut hal ini, @John Skeet dalam jawaban untuk pertanyaan lain ini ditambahkan Asyncke nama metode terlepas dari keberadaan asyncpengubah.

Terakhir, untuk pertanyaan lain , pertimbangkan komentar ini oleh @Damien_The_Unbeliever :

async/awaitadalah detail implementasi metode Anda. Tidak masalah apakah metode Anda dideklarasikan async Task Method()atau hanya Task Method(), sejauh menyangkut pemanggil Anda . (Faktanya, Anda bebas untuk mengubah di antara keduanya di lain waktu tanpa dianggap sebagai perubahan yang menghancurkan.)

Dari situ, saya menyimpulkan bahwa sifat asinkron dari metode yang menentukan bagaimana harus dinamai. Pengguna metode ini bahkan tidak akan tahu apakah asyncpengubah digunakan dalam implementasinya (tanpa kode sumber C # atau CIL).

DavidRR
sumber