Saya memiliki beberapa kode asinkron yang ingin saya tambahkan CancellationToken
. Namun, ada banyak implementasi yang tidak memerlukannya, jadi saya ingin memiliki parameter default - mungkin CancellationToken.None
. Namun,
Task<x> DoStuff(...., CancellationToken ct = null)
hasil
Nilai bertipe '' tidak dapat digunakan sebagai parameter default karena tidak ada konversi standar untuk mengetik 'System.Threading.CancellationToken'
dan
Task<x> DoStuff(...., CancellationToken ct = CancellationToken.None)
Nilai parameter default untuk 'ct' harus berupa konstanta waktu kompilasi
Apakah ada cara untuk memiliki nilai default CancellationToken
?
CancellationToken.None
menjadi sesuatu yang lebih dari itudefault(CancellationToken)
.default(CancellationToken)
dilakukan?CancellationToken.None
de facto tidak akan digunakan lagi. Bahkan Microsoft menggunakandefault(CancellationToken)
sebagai gantinya. Misalnya, lihat hasil pencarian ini dari kode sumber Kerangka Entitas.Sayangnya, ini tidak mungkin, karena
CancellationToken.None
bukan konstanta waktu kompilasi, yang merupakan persyaratan untuk nilai default dalam argumen opsional.Namun, Anda dapat memberikan efek yang sama dengan membuat metode kelebihan beban daripada mencoba menggunakan parameter default:
Task<x> DoStuff(...., CancellationToken ct) { //... } Task<x> DoStuff(....) { return DoStuff(...., CancellationToken.None); }
sumber
CancellationToken cancellationToken = default(CancellationToken)
? Juga dijelaskan di sini blogs.msdn.microsoft.com/andrewarnottms/2014/03/19/…Berikut adalah beberapa solusi, dalam urutan menurun dari kebaikan umum:
1. Menggunakan
default(CancellationToken)
sebagai nilai default:Task DoAsync(CancellationToken ct = default(CancellationToken)) { … }
Secara semantik,
CancellationToken.None
akan menjadi kandidat ideal untuk default, tetapi tidak dapat digunakan seperti itu karena ini bukan konstanta waktu kompilasi.default(CancellationToken)
adalah hal terbaik berikutnya karena merupakan konstanta waktu kompilasi dan didokumentasikan secara resmi sebagai padanannyaCancellationToken.None
.2. Menyediakan metode overload tanpa
CancellationToken
parameter:Atau, jika Anda lebih suka metode kelebihan beban daripada parameter opsional (lihat ini dan pertanyaan ini tentang topik itu):
Task DoAsync(CancellationToken ct) { … } // actual method always requires a token Task DoAsync() => DoAsync(CancellationToken.None); // overload producing a default token
Untuk metode antarmuka, hal yang sama dapat dicapai dengan menggunakan metode ekstensi:
interface IFoo { Task DoAsync(CancellationToken ct); } static class Foo { public static Task DoAsync(this IFoo foo) => foo.DoAsync(CancellationToken.None); }
Hal ini menghasilkan antarmuka yang lebih ramping dan mencegah pelaksana dari secara eksplisit menulis kelebihan metode penerusan.
3. Membuat parameter menjadi null dan menggunakan
null
sebagai nilai default:Task DoAsync(…, CancellationToken? ct = null) { … ct ?? CancellationToken.None … }
Saya suka solusi ini paling tidak karena jenis nullable datang dengan overhead runtime kecil, dan referensi ke token pembatalan menjadi lebih bertele-tele karena operator penggabungan null
??
.sumber
Opsi lainnya adalah menggunakan
Nullable<CancellationToken>
parameter, default kenull
, dan tangani di dalam metode:Task<x> DoStuff(...., CancellationToken? ct = null) { var token = ct ?? CancellationToken.None; ... }
sumber
Versi C # yang lebih baru memungkinkan sintaks yang disederhanakan untuk versi default (CancellationToken). Misalnya:
Task<x> DoStuff(...., CancellationToken ct = default)
sumber
Jawaban Tofutim adalah satu cara, tetapi dari komentar saya melihat bahwa orang-orang memiliki masalah dengan itu.
Dalam hal ini, saya menyarankan agar seseorang dapat memiliki metode sebagai berikut:
Task<x> DoStuff(...., CancellationToken ct) { }
dan membebani sebagai:
Task<x> DoStuff(....) { return DoStuff(...., CancellationToken.None); }
Ini mengkompilasi, karena nilai
CancellationToken.None
tidak diperlukan pada waktu kompilasi.sumber