Saya memiliki metode umum yang menerima permintaan dan memberikan tanggapan.
public Tres DoSomething<Tres, Treq>(Tres response, Treq request)
{/*stuff*/}
Tetapi saya tidak selalu menginginkan tanggapan untuk permintaan saya, dan saya tidak selalu ingin memberi makan data permintaan untuk mendapatkan tanggapan. Saya juga tidak ingin harus menyalin dan menempelkan metode secara keseluruhan untuk membuat perubahan kecil. Yang saya inginkan, adalah bisa melakukan ini:
public Tre DoSomething<Tres>(Tres response)
{
return DoSomething<Tres, void>(response, null);
}
Apakah ini layak dalam beberapa hal? Tampaknya secara khusus menggunakan void tidak berfungsi, tetapi saya berharap menemukan sesuatu yang serupa.
DoSomething(x);
bukannyay = DoSomething(x);
Jawaban:
Anda tidak dapat menggunakan
void
, tetapi Anda dapat menggunakanobject
: ini adalah sedikit ketidaknyamanan karena calonvoid
fungsi Anda harus dikembalikannull
, tetapi jika itu menyatukan kode Anda, itu harus menjadi harga yang kecil untuk dibayar.Ketidakmampuan untuk menggunakan
void
sebagai tipe pengembalian setidaknya sebagian bertanggung jawab atas pemisahan antaraFunc<...>
danAction<...>
keluarga delegasi umum: seandainya dimungkinkan untuk kembalivoid
, semuaAction<X,Y,Z>
akan menjadi sederhanaFunc<X,Y,Z,void>
. Sayangnya, ini tidak mungkin.sumber
void
dari metode yang akan dibatalkan itu, denganreturn System.Runtime.Serialization.FormatterServices.GetUninitializedObject(typeof(void));
. Ini akan menjadi kekosongan kotak.void
FP. Dan ada alasan bagus untuk menggunakannya. Di F #, masih .NET, kami memilikiunit
built-in.Tidak, sayangnya tidak. Jika
void
adalah tipe "nyata" (sepertiunit
di F # , misalnya) hidup akan jauh lebih sederhana dalam banyak hal. Secara khusus, kita tidak perlu keduaFunc<T>
danAction<T>
keluarga - ada hanya akanFunc<void>
bukanAction
,Func<T, void>
bukanAction<T>
dllIni juga akan membuat async lebih sederhana - sama sekali tidak diperlukan jenis non-generik
Task
- yang hanya akan kita milikiTask<void>
.Sayangnya, cara kerja sistem tipe C # atau .NET tidak seperti itu ...
sumber
Unfortunately, that's not the way the C# or .NET type systems work...
Anda membuat saya berharap bahwa mungkin semuanya akan berjalan seperti itu pada akhirnya. Apakah poin terakhir Anda berarti bahwa kita tidak akan pernah mengalami hal-hal seperti itu?Inilah yang dapat Anda lakukan. Seperti yang dikatakan @JohnSkeet tidak ada tipe unit di C #, jadi buat sendiri!
Sekarang Anda selalu dapat menggunakan
Func<..., ThankYou>
sebagai penggantiAction<...>
Atau gunakan sesuatu yang sudah dibuat oleh tim Rx: http://msdn.microsoft.com/en-us/library/system.reactive.unit%28v=VS.103%29.aspx
sumber
Install-Package System.Reactive.Core
Kthx.Bye;
Anda bisa menggunakan
Object
seperti yang disarankan orang lain. AtauInt32
yang saya lihat ada gunanya. MenggunakanInt32
memperkenalkan nomor "dummy" (penggunaan0
), tetapi setidaknya Anda tidak dapat memasukkan objek besar dan eksotis ke dalamInt32
referensi (struct disegel).Anda juga dapat menulis jenis "void" Anda sendiri:
MyVoid
referensi diperbolehkan (ini bukan kelas statis) tetapi hanya bisanull
. Konstruktor instance bersifat privat (dan jika seseorang mencoba memanggil konstruktor privat ini melalui refleksi, pengecualian akan dilemparkan ke mereka).Sejak tupel nilai diperkenalkan (2017, .NET 4.7), mungkin wajar untuk menggunakan struct
ValueTuple
(0-tupel, varian non-generik) daripada fileMyVoid
. Instance-nya memilikiToString()
pengembalian yang"()"
, jadi terlihat seperti tupel-nol. Pada versi C # saat ini, Anda tidak dapat menggunakan token()
dalam kode untuk mendapatkan sebuah instance. Anda dapat menggunakandefault(ValueTuple)
atau hanyadefault
(jika tipe dapat disimpulkan dari konteks) sebagai gantinya.sumber
Saya suka ide dari Aleksey Bykov di atas, tetapi ide tersebut bisa sedikit disederhanakan
Karena saya tidak melihat alasan yang jelas mengapa Nothing.AtAll tidak bisa begitu saja memberikan null
Ide yang sama (atau yang dibuat oleh Jeppe Stig Nielsen) juga bagus untuk digunakan dengan kelas yang diketik.
Misalnya, jika tipe hanya digunakan untuk mendeskripsikan argumen ke prosedur / fungsi yang dikirimkan sebagai argumen ke beberapa metode, dan itu sendiri tidak mengambil argumen apa pun.
(Anda masih perlu membuat bungkus tiruan atau mengizinkan "Tidak Ada" opsional. Tapi IMHO penggunaan kelas terlihat bagus dengan myClass <Nothing>)
atau
sumber
null
memiliki konotasi hilang atau tidak adaobject
. Memiliki hanya satu nilai untuk suatuNothing
sarana tidak pernah terlihat seperti yang lain.Nothing
disimpan dalam bidang statis pribadi dan menambahkan konstruktor pribadi. Fakta bahwa nol masih mungkin mengganggu, tapi itu akan diselesaikan, mudah-mudahan dengan C # 8.void
, meskipun sebuah tipe, hanya valid sebagai tipe kembalian dari sebuah metode.Tidak ada jalan keluar dari batasan ini
void
.sumber
Apa yang saat ini saya lakukan adalah membuat tipe tersegel khusus dengan konstruktor pribadi. Ini lebih baik daripada melemparkan pengecualian di c-tor karena Anda tidak perlu menunggu waktu proses untuk mengetahui situasinya salah. Ini secara halus lebih baik daripada mengembalikan instance statis karena Anda tidak perlu mengalokasikannya sekali pun. Ini secara halus lebih baik daripada mengembalikan statis null karena kurang bertele-tele di sisi panggilan. Satu-satunya hal yang dapat dilakukan pemanggil adalah memberikan null.
sumber