Haruskah C # metode yang * dapat * statis menjadi statis? [Tutup]

103

Haruskah metode C # yang bisa statis menjadi statis?

Kami mendiskusikan ini hari ini dan saya agak ragu. Bayangkan Anda memiliki metode panjang yang memfaktor ulang beberapa baris. Metode baru mungkin mengambil beberapa variabel lokal dari metode induk dan mengembalikan nilai. Artinya, ini bisa jadi statis.

Pertanyaannya adalah: haruskah itu statis? Ini tidak statis berdasarkan desain atau pilihan, hanya berdasarkan sifatnya yang tidak mereferensikan nilai contoh apa pun.

Bernhard Hofmann
sumber
41
"cukup tepat" adalah sebuah oxymoron
Matt Briggs
1
Resharper , alat alat Visual Studio, mengatakan ya! :-)
Rebecca
@Junto Mungkin dalam versi Anda, tapi versi saya mengatakan dapat dibuat statis ...
Robbie Dee

Jawaban:

59

Tergantung. Sebenarnya ada 2 jenis metode statis:

  1. Metode yang statis karena DAPAT
  2. Metode yang statis karena HARUS menjadi

Dalam basis kode ukuran kecil hingga sedang, Anda benar-benar dapat memperlakukan kedua metode tersebut secara bergantian.

Jika Anda memiliki metode yang termasuk dalam kategori pertama (can-be-static), dan Anda perlu mengubahnya untuk mengakses status kelas, relatif mudah untuk mencari tahu apakah mungkin mengubah metode statis menjadi metode instance.

Namun, dalam basis kode yang besar, banyaknya situs panggilan mungkin membuat penelusuran untuk melihat apakah mungkin untuk mengubah metode statis menjadi metode non-statis terlalu mahal. Banyak kali orang akan melihat jumlah panggilan, dan berkata "oke ... Lebih baik saya tidak mengubah metode ini, tetapi buat yang baru yang melakukan apa yang saya butuhkan".

Itu bisa mengakibatkan:

  1. Banyak duplikasi kode
  2. Ledakan jumlah argumen metode

Kedua hal itu buruk.

Jadi, saran saya adalah jika Anda memiliki basis kode lebih dari 200K LOC, saya hanya akan membuat metode statis jika metode tersebut harus menjadi metode statis.

Pemfaktoran ulang dari non-statis ke statis relatif mudah (cukup tambahkan kata kunci), jadi jika Anda ingin membuat can-be-static menjadi statis aktual nanti (saat Anda membutuhkan fungsionalitasnya di luar instance) maka Anda bisa. Namun, pemfaktoran ulang terbalik, mengubah can-be-static menjadi metode instance JAUH lebih mahal.

Dengan basis kode yang besar, lebih baik membuat kesalahan di sisi kemudahan ekstensi, daripada di sisi kemurnian idealogis.

Jadi, untuk proyek besar jangan membuat hal-hal statis kecuali Anda membutuhkannya. Untuk proyek kecil, lakukan saja apa yang paling Anda sukai.

Scott Wisniewski
sumber
43

Saya tidak akan menjadikannya anggota statis publik dari kelas itu . Alasannya adalah membuatnya menjadi statis publik berarti mengatakan sesuatu tentang tipe kelas: tidak hanya "tipe ini tahu bagaimana melakukan perilaku ini", tetapi juga "adalah tanggung jawab tipe ini untuk melakukan perilaku ini." Dan kemungkinan besar perilaku tersebut tidak lagi memiliki hubungan nyata dengan tipe yang lebih besar.

Itu tidak berarti saya tidak akan membuatnya statis sama sekali. Tanyakan pada diri Anda ini: dapatkah metode baru secara logis dimiliki oleh tempat lain? Jika Anda bisa menjawab "ya" untuk itu, Anda mungkin ingin membuatnya statis (dan memindahkannya juga). Bahkan jika itu tidak benar, Anda masih bisa membuatnya statis. Jangan tandai itu public.

Demi kenyamanan, Anda setidaknya bisa menandainya internal. Ini biasanya menghindari keharusan untuk memindahkan metode jika Anda tidak memiliki akses mudah ke jenis yang lebih sesuai, tetapi tetap membuatnya dapat diakses jika diperlukan dengan cara yang tidak akan muncul sebagai bagian dari antarmuka publik untuk pengguna kelas Anda .

Joel Coehoorn
sumber
6
Sepakat. Saya biasanya membuat metode "private static" dalam kasus seperti ini.
harpo
6
Saya juga tidak akan menganggap statis pribadi. Hal utama adalah bertanya pada diri sendiri: apakah metode ini secara logis cocok sebagai bagian dari jenis ini, atau hanya di sini hanya untuk kenyamanan? Jika yang terakhir, mungkinkah itu lebih cocok di tempat lain?
Joel Coehoorn
1
Seperti: "dapatkah metode baru secara logis dimiliki di tempat lain" - petunjuknya adalah tidak bergantung pada status lokal, mungkin tipe kembaliannya adalah tempatnya?
AndyM
20

Belum tentu.

Memindahkan metode publik dari statis ke non-statis adalah perubahan yang mengganggu, dan akan membutuhkan perubahan untuk semua penelepon atau konsumen Anda. Jika suatu metode tampak seperti metode contoh, tetapi kebetulan tidak menggunakan anggota contoh apa pun, saya sarankan menjadikannya sebagai metode contoh sebagai ukuran pemeriksaan masa depan.

Michael
sumber
Saya pikir dia kebanyakan mengacu pada metode pribadi
George Mauer
@Ray - Benar, ini hanya berlaku untuk anggota non-pribadi. Saya memperbarui jawaban saya untuk mencerminkan ini.
Michael
Pikiran saya persis - hanya karena Anda bisa membuat sesuatu statis tidak berarti Anda harus atau harus .....
marc_s
Jadi apa yang akan Anda lakukan untuk metode privat yang dapat dibuat statis?
Ray
@ Ray - Mungkin biarkan apa adanya sampai saya memiliki cukup alasan untuk pindah ke statis.
Michael
13

Iya. Alasan "itu bisa menjadi statis" adalah karena ia tidak beroperasi pada keadaan objek yang di atasnya ia dipanggil. Oleh karena itu, ini bukan metode instan, tetapi metode kelas. Jika itu dapat melakukan apa yang perlu dilakukan tanpa pernah mengakses data untuk contoh, maka itu harus statis.

JP Alioto
sumber
11

Ya, seharusnya. Ada berbagai metrik penggandengan yang mengukur bagaimana kelas Anda bergantung pada hal-hal lain, seperti kelas lain, metode, dll. Membuat metode statis adalah cara untuk menjaga tingkat penggandengan tetap rendah, karena Anda dapat yakin bahwa metode statis tidak mereferensikan apa pun anggota.

Jabe
sumber
7
Belum tentu. Metode statis tidak akan mengakses informasi instance, tidak ada anggota, seperti yang Anda katakan, tetapi dapat berinteraksi dengan kelas lain serta metode umum lainnya. Menjadi statis tidak berarti kopling berkurang. Namun, saya mengerti maksud Anda.
Victor Rodrigues
Sebaliknya statis sebenarnya meningkatkan kopling, karena Anda terbatas pada metode statis itu, tidak ada cara untuk iverride misalnya dan dengan demikian tidak ada cara untuk mengubah perilakunya.
HimBromBeere
8

Saya pikir itu akan membuatnya sedikit lebih mudah dibaca jika Anda menandainya sebagai statis ... Kemudian seseorang yang datang akan tahu bahwa itu tidak mereferensikan variabel instan apa pun tanpa harus membaca seluruh fungsi ...

Jason Punyon
sumber
6

Secara pribadi, saya penggemar berat keadaan tanpa kewarganegaraan. Apakah metode Anda memerlukan akses ke status kelas? Jika jawabannya tidak (dan mungkin tidak, jika tidak, Anda tidak akan mempertimbangkan menjadikannya metode statis), maka ya, lakukanlah.

Tidak ada akses ke negara lebih sedikit sakit kepala. Sama seperti ide yang baik untuk menyembunyikan anggota privat yang tidak dibutuhkan oleh kelas lain, merupakan ide yang baik untuk menyembunyikan status dari anggota yang tidak membutuhkannya. Akses yang berkurang dapat berarti lebih sedikit bug. Selain itu, ini membuat penguliran lebih mudah karena lebih mudah untuk menjaga anggota statis tetap aman. Ada juga pertimbangan performa karena runtime tidak perlu meneruskan referensi ini sebagai parameter untuk metode statis.

Tentu saja sisi negatifnya adalah jika Anda pernah menemukan bahwa metode statis Anda sebelumnya harus mengakses status karena alasan tertentu, maka Anda harus mengubahnya. Sekarang saya mengerti bahwa ini bisa menjadi masalah untuk API publik jadi jika ini adalah metode publik di kelas publik, mungkin Anda harus memikirkan implikasi dari ini sedikit. Tetap saja, saya belum pernah menghadapi situasi di dunia nyata di mana hal ini sebenarnya menyebabkan masalah, tapi mungkin saya hanya beruntung.

Jadi ya, lakukanlah, dengan segala cara.

Tamas Czinege
sumber
1
Metode statis masih dapat memiliki akses ke status. Itu hanya mendapatkan status dari objek yang diteruskan ke sana. Sebaliknya, kolom instance tidak selalu berisi status yang bisa berubah.
Jørgen Fogh
6

Metode statis lebih cepat daripada metode non-statis jadi ya, metode tersebut harus statis jika bisa dan tidak ada alasan khusus untuk membiarkannya nonstatis .

agnieszka
sumber
3
Itu benar secara teknis, tetapi tidak dalam arti material yang nyata. Perbedaan antara statis / non akan sangat, sangat jarang menjadi faktor kinerja.
Foredecker
22
-1: Optimasi prematur buku teks. Kecepatan tentunya tidak boleh menjadi kriteria pertama saat memutuskan statis vs. non-statis untuk kasus umum.
Tidak Yakin
2
Setuju dengan Tidak yakin, ini harus menjadi alasan terakhir Anda untuk mempertimbangkan statis vs tidak.
Samuel
5
Maksud saya adalah kecepatan adalah salah satu alasan termiskin yang dapat Anda miliki untuk memutuskan apakah suatu fungsi statis vs. non-statis dalam 99% kasus. Ada pertimbangan yang jauh lebih penting dalam hal desain OO yang diuraikan oleh pos lain.
Tidak Yakin
2
@agnieszka: Alasan khusus untuk umumnya menggunakan metode instance daripada metode statis adalah karena status. Jika Anda membiarkan metode Anda statis, dalam aplikasi yang kompleks Anda akan memperkenalkan bug yang akan membuat Anda merobek rambut Anda. Pikirkan tentang mengubah keadaan global, kondisi balapan, keamanan thread, dll.
Sandor Davidhazi
5

Saya terkejut bahwa begitu sedikit yang menyebutkan enkapsulasi di sini sebenarnya. Metode instance akan secara otomatis memiliki akses ke semua bidang, properti, dan metode pribadi (instance). Selain semua yang dilindungi yang diwarisi dari kelas dasar.

Ketika Anda menulis kode, Anda harus menulisnya sehingga Anda mengekspos sesedikit mungkin dan juga agar Anda memiliki akses ke sesedikit mungkin.

Jadi ya, mungkin penting untuk membuat kode Anda cepat yang akan terjadi jika Anda membuat metode Anda statis, tetapi biasanya lebih penting dari itu adalah membuat kode Anda tidak mampu membuat bug juga. Salah satu cara untuk mencapainya adalah membuat kode Anda memiliki akses ke sesedikit mungkin "barang pribadi".

Ini mungkin tampak tidak relevan pada pandangan pertama karena OP jelas berbicara tentang refactoring yang tidak bisa salah dalam skenario ini dan membuat bug baru, namun kode refactored ini harus dipertahankan di masa depan dan dimodifikasi yang membuat kode Anda memiliki serangan yang lebih besar. surface "terkait bug baru jika memiliki akses ke anggota instance pribadi. Jadi secara umum saya pikir kesimpulan di sini adalah bahwa "ya, sebagian besar metode Anda harus statis" kecuali ada alasan lain untuk tidak membuatnya statis. Dan ini hanya karena "penggunaan enkapsulasi dan penyembunyian data yang lebih baik serta membuat kode 'lebih aman'" ...

Thomas Hansen
sumber
4

Membuat sesuatu yang statis hanya karena Anda bisa bukanlah ide yang baik. Metode statis harus statis karena desainnya, bukan karena kebetulan.

Seperti yang dikatakan Michael, mengubah ini nanti akan merusak kode yang menggunakannya.

Dengan demikian, sepertinya Anda membuat fungsi utilitas privat untuk kelas yang sebenarnya statis menurut desain.

17 dari 26
sumber
4

Jika Anda dapat melakukan refaktorisasi beberapa baris dan metode yang dihasilkan dapat menjadi statis, ini mungkin merupakan indikasi bahwa garis yang Anda tarik keluar dari metode tersebut sama sekali tidak termasuk dalam kelas penampung, dan Anda harus mempertimbangkan untuk memindahkannya ke kelas mereka sendiri.

Chris Shaffer
sumber
2

Secara pribadi saya tidak punya pilihan selain membuatnya statis. Resharper mengeluarkan peringatan dalam kasus ini dan PM kami memiliki aturan "Tidak ada peringatan dari Resharper".

Prankster
sumber
1
Anda dapat mengubah pengaturan ReSharper Anda: P
Bernhard Hofmann
1
Jika begitu mudah kami tidak memiliki kerusakan dari Resharper ... pernah :)
Prankster
1

Itu tergantung tetapi umumnya saya tidak membuat metode tersebut statis. Kode selalu berubah dan mungkin suatu hari nanti saya ingin membuat fungsi itu virtual dan menggantinya dalam subclass. Atau mungkin suatu hari nanti perlu mereferensikan variabel instan. Akan lebih sulit untuk membuat perubahan tersebut jika setiap situs panggilan harus diubah.

Brian Ensink
sumber
Ya, tetapi jika suatu hari Anda perlu melakukan ini, Anda selalu dapat membuatnya tidak statis. Atau apakah saya melewatkan sesuatu?
Ray
1
@Ray - Saya menutupi ini dalam jawaban saya. statis menjadi non-statis adalah perubahan yang mengganggu, sehingga semua konsumen perlu dimodifikasi. Bukan masalah besar untuk program kecil, tetapi jika itu adalah perpustakaan untuk dikonsumsi oleh orang lain, ini harus diperhitungkan.
Michael
Semua situs panggilan harus diubah dari panggilan metode statis menjadi panggilan fungsi anggota.
Brian Ensink
Maaf, Anda menambahkannya setelah komentar saya. Dalam pikiran saya, saya berpikir tentang metode privat, tetapi itu poin yang valid untuk metode publik.
Ray
... atau suatu hari Anda bisa membuangnya. Argumen ini tidak cukup untuk saya membuat metode nonstatic.
agnieszka
1

Saya menyarankan bahwa cara terbaik untuk memikirkannya adalah ini: Jika Anda memerlukan metode kelas yang perlu dipanggil ketika tidak ada instance kelas yang instan, atau mempertahankan beberapa jenis status global, statis adalah ide yang bagus. Tapi secara umum, saya sarankan Anda lebih memilih membuat member non-static.

Foredecker
sumber
1

Anda harus memikirkan metode dan kelas Anda:

  • Bagaimana Anda akan menggunakannya?
  • Apakah Anda memerlukan banyak akses ke mereka dari berbagai level kode Anda?
  • Apakah ini metode / kelas yang dapat saya gunakan di hampir setiap proyek yang dapat dipikirkan.

Jika dua yang terakhir adalah 'ya', maka metode / kelas Anda mungkin harus statis.

Contoh yang paling sering digunakan mungkin adalah Mathkelasnya. Setiap bahasa OO utama memilikinya dan semua metodenya statis. Karena Anda harus dapat menggunakannya di mana saja, kapan saja, tanpa membuat contoh.

Contoh bagus lainnya adalah Reverse()metode di C #.
Ini adalah metode statis di Arraykelas. Ini membalik urutan array Anda.

Kode:

public static void Reverse(Array array)

Ia bahkan tidak mengembalikan apapun, array Anda dibalik, karena semua array adalah instance dari kelas Array.

KdgDev
sumber
Matematika adalah contoh yang buruk. Saya kira itu lebih baik: newnumber = number.round (2) daripada newnumber = Math.round (nomor)
graffic
3
Kelas Matematika adalah contoh sempurna dalam menggunakan kelas statis. Tentang itulah topik ini, bukan tentang bagaimana Anda lebih suka membulatkan angka ...
KdgDev
1

Selama Anda membuat metode baru menjadi privat statis, itu bukan perubahan yang mengganggu. Faktanya, FxCop menyertakan panduan ini sebagai salah satu aturannya ( http://msdn.microsoft.com/en-us/library/ms245046(VS.80).aspx ), dengan informasi berikut:

Setelah Anda menandai metode sebagai statis, kompilator akan memancarkan situs panggilan non-virtual ke anggota ini. Memancarkan situs panggilan non-virtual akan mencegah pemeriksaan pada waktu proses untuk setiap panggilan yang memastikan bahwa penunjuk objek saat ini bukan null. Hal ini dapat menghasilkan peningkatan kinerja yang dapat diukur untuk kode yang sensitif terhadap kinerja. Dalam beberapa kasus, kegagalan untuk mengakses contoh objek saat ini merupakan masalah kebenaran.

Meskipun demikian, komentar pertama dari David Kean secara lebih ringkas merangkum kekhawatiran dengan mengatakan ini sebenarnya lebih tentang menjadi benar daripada tentang perolehan kinerja:

Meskipun aturan ini diklasifikasikan sebagai masalah kinerja, peningkatan kinerja membuat metode statis hanya sekitar 1%. Sebaliknya, ini lebih merupakan masalah kebenaran yang dapat mengindikasikan ketidaklengkapan atau bug pada anggota karena kegagalannya untuk menggunakan anggota contoh lainnya. Menandai metode sebagai statis ( Dibagikan dalam Visual Basic) menjelaskan maksudnya untuk tidak menyentuh status instance.

Scott Dorman
sumber
1

Saya pasti akan mengubah apa pun yang saya bisa menjadi statis karena alasan yang berbeda:

Fungsi statis, ketika JIT, dipanggil tanpa parameter "ini". Itu berarti, misalnya, bahwa 3 parameter fungsi non-statis (metode anggota) didorong dengan 4 parameter pada tumpukan.

Fungsi yang sama yang dikompilasi sebagai fungsi statis akan dipanggil dengan 3 parameter. Ini dapat membebaskan register untuk JIT dan menghemat ruang tumpukan ...

damageboy
sumber
1

Saya berada di kamp "hanya membuat metode pribadi statis". Membuat metode publik dapat memperkenalkan kopling yang tidak Anda inginkan dan dapat menurunkan kemampuan pengujian: Anda tidak dapat menghentikan metode statis publik.

Jika Anda ingin menguji unit metode yang menggunakan metode statis publik, Anda akhirnya menguji metode statis juga, yang mungkin bukan yang Anda inginkan.

Lennaert
sumber
1

Metode statis yang melekat yang karena alasan tertentu dibuat non-statis cukup mengganggu. Yakni:

Saya menelepon bank saya dan meminta saldo saya.
Mereka meminta nomor rekening saya.
Cukup adil. Metode instance.

Saya menelepon bank saya dan menanyakan alamat surat mereka.
Mereka meminta nomor rekening saya.
WTF? Gagal — seharusnya metode statis.

IJ Kennedy
sumber
1
Bagaimana jika pelanggan yang berbeda dilayani oleh cabang yang berbeda? Mengirimkan korespondensi ke kantor utama bank mungkin akan membawanya ke cabang yang tepat, pada akhirnya, tetapi itu tidak berarti bahwa pelanggan tidak akan dilayani dengan lebih baik dengan menggunakan alamat cabang tertentu yang melayaninya.
supercat
0

Saya melihatnya secara umum dari perspektif fungsional fungsi murni. Apakah itu perlu metode contoh? Jika tidak, Anda bisa mendapatkan keuntungan dari memaksa pengguna untuk memasukkan variabel dan tidak merusak status instance saat ini. (Yah, Anda masih bisa mengacaukan status, tetapi intinya adalah, secara desain, tidak melakukannya.) Saya biasanya merancang metode contoh sebagai anggota publik dan melakukan yang terbaik untuk membuat anggota pribadi statis. Jika perlu (Anda dapat mengekstraknya dengan lebih mudah ke kelas lain nanti.


sumber
-1

Dalam kasus tersebut, saya cenderung memindahkan metode ke pustaka statis atau utils, jadi saya tidak akan mencampur konsep "objek" dengan konsep "kelas"

Jhonny D. Cano -Leftware-
sumber