C # atau .Net fitur untuk memotong dengan asumsi tidak diperlukan kompatibilitas mundur? [Tutup]

18

Setiap produk atau kerangka kerja berevolusi. Terutama itu dilakukan untuk mengejar kebutuhan pengguna itu, memanfaatkan kekuatan komputasi baru dan hanya membuatnya lebih baik. Terkadang tujuan desain utama juga berubah dengan produk. Kerangka kerja C # atau .net tidak terkecuali. Seperti yang kita lihat, versi 4 hari ini sangat berbeda dibandingkan dengan yang pertama. Tetapi hal datang sebagai barikade untuk kompatibilitas-mundur evolusi ini.

Dalam sebagian besar kerangka kerja / produk ada fitur yang akan terputus jika tidak perlu mendukung kompatibilitas mundur. Menurut Anda, apa saja fitur ini di C # /. Net?

Harap sebutkan satu fitur per jawaban.

Gulshan
sumber
Kata kunci baru
Nemanja Trifunovic
4
Pertanyaannya jelas tidak konstruktif sesuai dengan pedoman, dan jelas konstruktif berdasarkan jawaban fantastis. Voting untuk membuka kembali.
psr
1
Sayang sekali sudah ditutup, masih mungkin Eric akan menulis blog ini daripada menjawab di sini?
jk.

Jawaban:

35

Metode anonim . Saya pikir semua orang setuju bahwa sintaksis metode anonim yang dipilih untuk C # 2.0 adalah chunky dan clunky dibandingkan dengan sintaks lambda yang kita tambahkan ke C # 3.0. Sangat disayangkan memiliki dua sintaksis yang hampir identik untuk melakukan hal yang sama.

Eric Lippert
sumber
1
Setuju, metode anonim sangat bagus ketika kita tidak memiliki lambda ... sekarang mereka hanya berlebihan.
Michael Brown
9
Ada satu fitur khusus dari metode anonim yang jauh lebih baik daripada ekspresi lambda .... nama mereka yang sempurna !!
explorest
1
Pada titik ini, saya bahkan tidak ingat sintaks untuk metode anonim dalam C #. Saya harus mencarinya jika karena alasan yang aneh saya perlu menggunakan satu bukan lambda.
Kyralessa
33

Saya akan menyingkirkan koleksi Non-generik. Mereka adalah kekejian ... dan ada terlalu banyak kasus di mana saya menggunakan LINQ dan harus melakukan sesuatu seperti

var customObjects = container.CustomObjects.Cast<CustomObject>();

Setiap kali saya harus melakukan itu, sebagian kecil dari jiwa saya mati.

Michael Brown
sumber
Ini terlalu hebat.
1
Tidak semua port .NET mendukung Generics. .NET Micro adalah contohnya. Mungkin tidak berlaku jika CustomObjects tidak akan pernah pindah ke platform ini.
goodguys_activate
2
Itulah keuntungan dari tidak memiliki jiwa.
CaffGeek
29

batal sebagai tipe . Mengapa "void" adalah tipe? Tidak memiliki instance, tidak memiliki nilai, Anda tidak dapat menggunakannya sebagai argumen tipe generik, tipe parameter formal, tipe lokal, tipe bidang, atau tipe properti. Itu tidak memiliki arti sebagai tipe; melainkan, ini adalah fakta tentang apa efek pemanggilan metode terhadap tumpukan mesin virtual. Tapi mesin virtual itu hanya itu: mesin virtual. Mesin nyata akan memasukkan nilai yang dikembalikan ke register (biasanya EAX pada x86) dan tidak mempengaruhi tumpukan sama sekali! Batal sebagai tipe hanya ide buruk di sekitar.

Lebih buruk: ketika digunakan dalam jenis pointer seperti di void*dalamnya berarti sesuatu yang sama sekali berbeda dari apa artinya ketika digunakan sebagai tipe pengembalian. Sekarang ini berarti "penunjuk ke lokasi penyimpanan dengan tipe yang tidak dikenal", yang tidak ada hubungannya dengan artinya sebagai "metode yang tidak mengembalikan nilai apa pun."

Kita dapat mengganti void*dengan tipe pointer dengan IntPtr. (Dan void**dengan IntPtr*dan seterusnya.) Kita dapat mengganti void sebagai tipe kembali dengan "Unit", tipe yang memiliki nilai tunggal, yaitu, null. Implementasi CLR kemudian dapat memutuskan bahwa panggilan fungsi unit-typed dapat mengoptimalkan penggunaan register atau tumpukan dengan tepat, mengetahui bahwa null yang sedang "dikembalikan" dapat diabaikan dengan aman.

Di dunia seperti itu Anda tidak perlu lagi terpisah Func<A, R>dan Action<T>mendelegasikan. Action<T>hanya Func<T, Unit>.

Eric Lippert
sumber
4
... dan Taskhanya a Task<Unit>. Mengimplementasikan kembali bit perpustakaan dari CTP async membuat saya benar-benar berharap untuk ini ...
Jon Skeet
24

Pernyataan kosong; . Rawan kesalahan, hampir selalu salah ketik, dan tidak memberi Anda makna tambahan yang belum diungkapkan oleh {}.

Eric Lippert
sumber
7
Belum lagi penalti performa yang luar biasa di bawah JIT 64-bit </snark>.
Jesse C. Slicer
7
Pernyataan kosong memiliki penalti kinerja? Mengapa demikian?
quentin-starin
22

Kovarians tidak aman pada array jenis referensi . Dengan aktifnya kovarians typesafe IEnumerable<T>, setidaknya sebagian kebutuhan akan kovarians array telah hilang. (Jika kita memiliki antarmuka daftar read-only kovarian maka kita tidak akan memerlukannya sama sekali.)

Eric Lippert
sumber
Saya benar-benar akan menuliskan ini ketika saya melihat judul pertanyaan - Anda mengalahkan saya untuk itu :(
Chris Smith
1
Kemampuan untuk menerima referensi array kovarian dan dengan aman menulis ke referensi array yang dibaca darinya bermanfaat. Jika suka IList<T>diwarisi dari IReadableList<out T>dan non-generik IPemutable, itu bisa mendukung hal-hal seperti penyortiran, tetapi array mendukungnya dengan lebih mudah.
supercat
14

Operator plus unary . Operator yang paling tidak berguna sepanjang masa. Jika kita tidak harus menyimpannya untuk backat compat, aku akan mengeluarkannya dalam sekejap. Siapa yang menggunakan benda ini, siapa pun?

(Klarifikasi: Operator unary plus +xbukan operator preincrement ++x, bukan operator postincrement x++dan bukan operator penambahan biner x+y.)

Eric Lippert
sumber
1
untuk (int i = 0; i <ceiling; i ++)
Michael Brown
13
Dia tidak berbicara tentang preinkremen dan operator postincrement: dia berbicara tentang plus unary, kebalikan dari tanda negatif pada nomor: +1 == 1. Ini sangat dekat dengan no-op.
Jesse C. Slicer
8
Ini bukan hanya tentang efek pada mesin keluaran dibaca, dapat meningkatkan tampilan kode untuk manusia: if(a == +1 || a == -1){...}.
Thomas Bratt
5
@ ShuggyCoUK: Apa yang sangat aneh tentang itu adalah kelebihan muatan . Karena itu sering terjadi. Anda tahu, bagaimana Anda menulis JavaScript dan menurut Anda , saya berharap JS mengizinkan saya membuat semantik yang ditetapkan pengguna plus semantik operator seperti yang dilakukan C # .
Eric Lippert
2
@ Eric, saya tidak menyadari itu kelebihan beban. wow Anda bisa melakukan beberapa kebingungan jahat dengan itu :)
ShuggyCoUk
12

Mengalihkan literal angka ke double

Untuk sebagian besar aplikasi bisnis , decimalitu lebih tepat ... atau mungkin akan lebih baik untuk adil menghapus ide default, dan memaksa pengembang untuk benar-benar membuat pilihan.

(Itu "menghapus default" akan sesuai untuk beberapa hal lain, juga. Sebagai contoh, saya sudah menyerah berusaha membujuk semua orang bahwa kelas harus ditutup secara default, tapi saya menduga lebih mudah untuk meyakinkan orang bahwa mereka harus berpikir tentang apakah kelas baru mereka harus disegel atau tidak, dan membuatnya eksplisit.)

Jon Skeet
sumber
Saya mungkin akan condong untuk mengidentifikasi literal yang menyiratkan nilai yang tidak dapat direpresentasikan sebagai double / float tepatnya ...
ShuggyCoUk
Jika mereka ke Jawa - merujuknya ke teks suci oleh Joshua Bloch "desain atau dokumen untuk warisan atau melarangnya" martinfowler.com/bliki/DesignedInheritance.html IIRC kotlin melakukan segel kelas secara default, sehingga industri ini pindah ke arah yang lebih baik dalam hal ini.
Elazar Leibovich
Mengapa kelas harus disegel?
James
@ James: Untuk alasan yang diberikan Josh. Merancang kelas yang memungkinkan pewarisan dengan cara yang masuk akal dan konsisten membutuhkan waktu - dan melakukannya tanpa mengetahui bagaimana warisan akan digunakan bahkan lebih buruk.
Jon Skeet
1
@Pacerier: Pikirkan tentang kekekalan, misalnya. Kelas yang tidak dimeteraikan tidak dapat mengklaim tidak dapat diubah, karena subclass dapat memperkenalkan mutabilitas.
Jon Skeet
7

Ini lebih merupakan pedoman daripada fitur, tapi saya pikir ini penting karena sudah terlalu tertanam dalam pikiran orang sebagai solusi kanonik dan terbaik:

The Pola resmi untuk melaksanakan IDisposable.

Ini rumit dan ada cara yang lebih baik .

Jordão
sumber
6

Saya tahu ada perbedaan besar antara berbagai kelas pengatur waktu. Tetapi, tidak bisakah kita menyingkirkan satu atau dua dari mereka?

nikie
sumber
4

Metode dan jenis Arraydan List<T>yang menjadi usang dengan Linq, misalnya:

  • Array.TrueForAll dapat diganti dengan Enumerable.All
  • Array.FindAll dapat diganti dengan Enumerable.Where
  • List<T>.ConvertAll dapat diganti dengan Enumerable.Select
  • Predicate<T> dapat diganti dengan Func<T, bool>
  • Converter<T,R> dapat diganti dengan Func<T, R>
  • IComparer<T> benar-benar harus menjadi delegasi Func<T, T, int>
nikie
sumber
3
Saya suka Predicate<T>karena menangkap maksud tentang bagaimana fungsi ini digunakan dan menyimpan sedikit pengetikan.
Zebi
2

Delegasi Non-generik Seperti koleksi non-generik, delegasi non-generik sekarang tidak berguna karena kita memiliki seri Func and Action. Dan saya akan memotong varian di tiga parameter. Jika Anda memiliki lebih dari tiga parameter, buat struktur dan gunakan itu sebagai parameter tunggal. Mendeklarasikan delegasi khusus untuk penanganan acara tidak terlalu KERING.

Michael Brown
sumber
3
Bagaimana Anda mendefinisikan delegasi ke metode yang mengambil ref dengan Action atau Func? Bagaimana Anda mendefinisikan kombinator dengan Func? Artinya, tidak ada cara untuk mengatakan "mendelegasikan DD (D d);" dengan Func.
Eric Lippert
2
hmmm ... saya berdiri terkoreksi. Itu sebabnya saya meninggalkan pekerjaan menciptakan alat yang saya gunakan di tangan Anda yang cakap;)
Michael Brown
@EricLippert: Saya ingin melihat kelas delegasi khusus yang akan melalui CLR magic berisi delegasi dari "setiap" arity dan kombinasi parameter nilai / referensi [mencari seorang delegasi di kelas sihir dengan nama yang diformat sesuai akan menciptakan ketik], dan minta semua delegasi dari tanda tangan yang tepat mewarisi itu. Kode yang menginginkan delegasi tertentu masih memerlukan jenis yang tepat, tetapi kode yang menginginkan tanda tangan tertentu dapat menggunakan nama ajaib.
supercat
-1

Layanan Web asmx

Saya pikir mereka cukup usang dengan WCF saat ini.

fretje
sumber
6
Ya, tapi terkadang jauh lebih mudah untuk grok. . .
Wyatt Barnett
-2

Winforms
Alangkah baiknya tidak harus menavigasi antara dua platform desktop. WPF adalah tujuan, jadi frustasi untuk memiliki redundansi tingkat platform penuh.

Morgan Herlocker
sumber
Winforms tampaknya jauh lebih stabil, lebih cepat, dan lebih sedikit buggy daripada WPF ...
Pacerier
Ketika Anda hanya perlu meretas aplikasi desktop kecil, WPF adalah pembunuhan besar-besaran.
Kyralessa
Tampaknya di antara WPF telah menjadi cukup usang dalam mendukung WinRT. Namun, bagi saya sepertinya Winforms lebih hidup daripada WPF dalam pengembangan bisnis. Lihat juga stackoverflow.com/questions/913417/…
Doc Brown