Statik * olabilen * C # yöntemleri statik olmalı mı? [kapalı]


103

Statik olabilen C # yöntemleri statik olmalı mı?

Bugün bunu tartışıyorduk ve ben biraz telaşlanıyorum. Birkaç satırı yeniden düzenlediğiniz uzun bir yönteminiz olduğunu hayal edin. Yeni yöntem muhtemelen üst yöntemden birkaç yerel değişken alır ve bir değer döndürür. Bu, statik olabileceği anlamına gelir .

Soru şu: statik olmalı mı? Tasarım veya seçim gereği statik değildir, sadece herhangi bir örnek değerine referans vermemesi nedeniyle doğası gereği.


1
Oldukça kesin bir yinelenen stackoverflow.com/questions/169378/...
JasonTrue

41
"oldukça doğru" bir tezattır
Matt Briggs

1
Araçların Visual Studio aracı olan Resharper , evet diyor! :-)
Rebecca

@Junto Belki sürümünde, ama benim diyor olabilir ... statik yapılabilir
Robbie Dee

Yanıtlar:


59

Değişir. Gerçekten 2 tür statik yöntem vardır:

  1. Olabilir çünkü statik olan yöntemler
  2. ZORUNLU olmaları nedeniyle statik olan yöntemler

Küçük ve orta büyüklükte bir kod tabanında, iki yöntemi birbirinin yerine gerçekten ele alabilirsiniz.

İlk kategoride (statik olabilir) bir yönteminiz varsa ve bunu sınıf durumuna erişmek için değiştirmeniz gerekiyorsa, statik yöntemi bir örnek yönteme dönüştürmenin mümkün olup olmadığını anlamak nispeten kolaydır.

Bununla birlikte, büyük bir kod tabanında, çok sayıda arama sitesi, statik bir yöntemi statik olmayan bir yönteme çok pahalıya dönüştürmenin mümkün olup olmadığını görmek için arama yapabilir. Çoğu zaman insanlar arama sayısını görecek ve "tamam ... Bu yöntemi değiştirmesem iyi olur, bunun yerine ihtiyacım olanı yapacak yeni bir tane yaratırım" der.

Bu, şunlardan birine neden olabilir:

  1. Çok fazla kod kopyası
  2. Yöntem bağımsız değişkenlerinin sayısında patlama

Bunların ikisi de kötü.

Bu nedenle, tavsiyem, eğer 200K LOC üzerinde bir kod tabanınız varsa, yöntemleri yalnızca statik olmaları gereken yöntemler ise statik hale getiririm.

Statik olmayandan statik olana yeniden düzenleme nispeten kolaydır (sadece bir anahtar kelime ekleyin), bu nedenle, daha sonra statik olabilen bir statik haline getirmek istiyorsanız (bir örneğin dışında işlevselliğe ihtiyaç duyduğunuzda) yapabilirsiniz. Ancak, statik olabilen bir yöntemi örnek yöntemine dönüştürmek ÇOK daha pahalıdır.

Büyük kod tabanları söz konusu olduğunda, idealojik saflıktan ziyade genişletme kolaylığı açısından hata yapmak daha iyidir.

Bu nedenle, büyük projeler için ihtiyacınız olmadıkça işleri statik hale getirmeyin. Küçük projeler için, en sevdiğiniz şeyi yapın.


43

Ben ediyorum değil bir hale kamu statik üyesi , bu sınıfın . Bunun nedeni, onu genel statik hale getirmenin sınıfın türü hakkında bir şeyler söylemesidir: yalnızca "bu tür bu davranışı nasıl yapacağını bilir" değil, aynı zamanda "bu davranışı gerçekleştirmek bu türün sorumluluğudur". Ve olasılıklar, davranışın artık daha büyük türle gerçek bir ilişkisi olmamasıdır.

Yine de bu, onu hiç statik yapmayacağım anlamına gelmez. Kendinize şunu sorun: Yeni yöntem mantıksal olarak başka bir yere ait olabilir mi? Buna "evet" cevabını verebiliyorsanız, muhtemelen onu statik yapmak (ve aynı zamanda hareket ettirmek) istersiniz. Bu doğru olmasa bile, yine de statik hale getirebilirsiniz. Sadece işaretlemeyin public.

Kolaylık açısından en azından işaretleyebilirsiniz internal. Bu genellikle, daha uygun bir türe kolay erişiminiz yoksa yöntemi taşıma ihtiyacını ortadan kaldırır, ancak yine de gerektiğinde sınıfınızın kullanıcılarına ortak arayüzün bir parçası olarak görünmeyecek şekilde onu erişilebilir bırakır. .


6
Kabul. Genelde böyle bir durumda yöntemi "özel statik" yapıyorum.
harpo

6
Ben de özel statik varsaymazdım. Önemli olan kendinize şu soruyu sormaktır: Bu yöntem mantıklı olarak bu türün bir parçası olarak mı uyuyor, yoksa burada bir kolaylık meselesi mi? İkincisi ise, başka bir yere daha iyi uyabilir mi?
Joel Coehoorn

1
Mesela: "Yeni yöntem mantıksal olarak başka bir yere ait olabilir" - ipucu, yerel duruma bağlı olmaması, belki de dönüş türü ait olduğu yerdir?
AndyM

20

Şart değil.

Genel yöntemleri statikten statik olmayana taşımak, büyük bir değişikliktir ve tüm arayanlarınız veya tüketicilerinizde değişiklik yapılmasını gerektirir. Bir yöntem bir örnek yöntemi gibi görünüyorsa, ancak herhangi bir örnek üyesi kullanmıyorsa, geleceğe yönelik bir önlem olarak onu bir örnek yöntem yapmayı öneririm.


Sanırım çoğunlukla özel yöntemlere atıfta bulunuyor
George Mauer

@Ray - Doğru, bu yalnızca özel olmayan üyeler için geçerlidir. Cevabımı bunu yansıtacak şekilde güncelledim.
Michael

Tam olarak düşüncelerim - statik bir şey yapabilmeniz , yapmanız ya da yapmanız gerektiği anlamına gelmez .....
marc_s

Peki, statik hale getirilebilecek özel yöntemler için ne yapardınız?
Ray

@Ray - Statike geçmek için yeterince nedenim olana kadar muhtemelen olduğu gibi bırakın.
Michael

13

Evet. "Statik olabilmesinin" nedeni, çağrıldığı nesnenin durumu üzerinde çalışmamasıdır. Bu nedenle, bir örnek yöntem değil, bir sınıf yöntemidir. Örnek için verilere hiç erişmeden yapması gerekeni yapabiliyorsa, statik olmalıdır.


11

Evet olmalı. Diğer sınıflar, yöntemler vb. Gibi sınıfınızın diğer şeylere nasıl bağlı olduğunu ölçen çeşitli eşleştirme ölçütleri vardır . Yöntemleri statik yapmak, birleştirme derecesini düşük tutmanın bir yoludur, çünkü statik bir yöntemin herhangi bir yönteme başvurmadığından emin olabilirsiniz. üyeler.


7
Şart değil. Statik bir yöntem, örnek bilgilerine erişmez, hiçbir üyeye, sizin söylediğiniz gibi erişmez, ancak diğer sınıflarla ve başka bir yaygın yöntemle etkileşime girebilir. Statik olmak, mutlaka bağlantının azaltıldığı anlamına gelmez. Ancak, ne demek istediğini anladım.
Victor Rodrigues,

Bunun yerine, statik gerçek , birleştirmeyi artırır , çünkü tam olarak bu statik yöntemle sınırlısınız, örneğin onu geçersiz kılmanın bir yolu yoktur ve dolayısıyla davranışı değiştirmenin bir yolu yoktur .
HimBromBeere

8

Statik olarak işaretlerseniz biraz daha okunaklı hale getireceğini düşünüyorum ... O zaman gelen biri, tüm işlevi okumak zorunda kalmadan herhangi bir örnek değişkenine başvurmadığını bilecektir ...


6

Şahsen ben vatansızlığın büyük bir hayranıyım. Yönteminizin sınıfın durumuna erişmesi gerekiyor mu? Cevap hayır ise (ve muhtemelen hayır ise, aksi takdirde onu statik bir yöntem yapmayı düşünmezsiniz), o zaman evet, devam edin.

Eyalete erişimin olmaması daha az baş ağrısıdır. Diğer sınıflar tarafından ihtiyaç duyulmayan özel üyeleri gizlemek iyi bir fikir olduğu gibi, devleti buna ihtiyaç duymayan üyelerden gizlemek de iyi bir fikirdir. Daha az erişim, daha az hata anlamına gelebilir. Ayrıca, statik üyeleri iş parçacığı açısından güvenli tutmak çok daha kolay olduğu için diş açmayı kolaylaştırır. Çalışma zamanı bir başvuru geçmesi gerekmez gibi bir performans göz de bulunmaktadır , bu statik yöntemler için bir parametre olarak.

Elbette dezavantajı, önceden statik yönteminizin herhangi bir nedenle duruma erişmesi gerektiğini fark ederseniz, o zaman onu değiştirmeniz gerekir. Şimdi anlıyorum ki, bu genel API'ler için bir sorun olabilir, bu yüzden bu genel bir sınıfta genel bir yöntemse, o zaman belki de bunun etkileri hakkında biraz düşünmelisiniz. Yine de, gerçek dünyada bunun gerçekten bir soruna neden olduğu bir durumla hiç karşılaşmadım, ama belki de sadece şanslıyım.

Yani evet, elbette bunun için gidin.


1
Statik bir yöntemin duruma yine de erişimi olabilir. Sadece kendisine iletilen nesneden durumu alır. Tersine, örnek alanlarının değişebilir durum içermesi gerekmez.
Jørgen Fogh

6

Statik yöntemler statik olmayan yöntemlerden daha hızlıdır, bu nedenle evet, yapabiliyorlarsa statik olmalıdırlar ve onları durağan bırakmanın özel bir nedeni yoktur .


3
Bu teknik olarak doğrudur, ancak gerçek maddi anlamda değil. Statik / non arasındaki fark çok, çok nadiren performansta bir faktör olacaktır.
Foredecker

22
-1: Ders kitabında erken optimizasyon. Genel durum için statik ve statik olmayan arasında karar verirken hız kesinlikle ilk kriter olmamalıdır.
Değil Emin

2
Emin Değil ile aynı fikirde olun, bu, statik olup olmadığını düşünmek için son nedeniniz olmalıdır .
Samuel

5
Demek istediğim, hız, vakaların% 99'unda bir fonksiyonun statik mi yoksa statik olmayan mı olduğuna karar vermenin en zayıf nedenlerinden biri. OO tasarımı söz konusu olduğunda, diğer yayınların üzerinde durduğu çok daha önemli hususlar vardır.
Emin Değil

2
@agnieszka: Genelde statik yöntemler yerine örnek yöntemlerini kullanmanın özel nedeni state'dir. Yöntemleri statik bırakırsanız, karmaşık bir uygulamada saçınızı yırtmanıza neden olacak böcekleri ortaya çıkaracaksınız. Küresel durumu, yarış koşullarını, iş parçacığı güvenliğini vb. Değiştirmeyi düşünün
Sandor Davidhazi

5

Aslında burada bu kadar az kişinin kapsüllemeden bahsetmesine şaşırıyorum. Bir örnek yöntemi, tüm özel (örnek) alanlara, özelliklere ve yöntemlere otomatik olarak erişebilir. Temel sınıflardan miras alınan tüm korumalı olanlara ek olarak.

Kodu yazarken, onu mümkün olduğunca az açığa çıkaracak ve ayrıca olabildiğince az erişime sahip olacak şekilde yazmalısınız.

Dolayısıyla, evet, kodunuzu hızlı yapmak önemli olabilir, bu yöntem yöntemlerinizi statik hale getirirseniz olur, ancak genellikle daha da önemlisi, kodunuzu da mümkün olduğunca hata yaratamaz hale getirmektir. Bunu başarmanın bir yolu, kodunuzun olabildiğince az "özel şeylere" erişimini sağlamaktır.

Bu ilk bakışta alakasız görünebilir, çünkü OP açıkça bu senaryoda yanlış gidemeyen ve yeni hatalar yaratamayan yeniden düzenleme hakkında konuşuyor, ancak bu yeniden düzenlenmiş kod gelecekte korunmalı ve kodunuzun daha büyük bir saldırıya sahip olmasını sağlayacak şekilde değiştirilmelidir. özel örnek üyelerine erişimi varsa yeni hatalarla ilgili olarak yüzey ". Dolayısıyla, genel olarak bence buradaki sonuç, statik olmamak için başka nedenler olmadığı sürece "evet, çoğunlukla yöntemleriniz statik olmalıdır" . Ve bunun nedeni, "kapsülleme ve veri gizlemenin daha iyi kullanılması ve" daha güvenli "kod yaratmasıdır" ...


4

Yapabileceğin için statik bir şey yapmak iyi bir fikir değil. Statik yöntemler tesadüfen değil, tasarımları nedeniyle statik olmalıdır.

Michael'ın dediği gibi, bunu daha sonra değiştirmek onu kullanan kodu bozacaktır.

Bununla birlikte, aslında tasarım gereği statik olan sınıf için özel bir yardımcı program işlevi yaratıyormuşsunuz gibi görünüyor.


4

Birkaç satırı yeniden düzenleyebildiyseniz ve ortaya çıkan yöntem statik olabilirse, bu muhtemelen bu yöntemden çıkardığınız satırların içerdiği sınıfa ait olmadığının bir göstergesidir ve bunları içine taşımayı düşünmelisiniz. kendi sınıfları.


2

Şahsen bunu statik yapmaktan başka seçeneğim kalmazdı. Yeniden Paylaşıcı bu durumda bir uyarı verir ve Yönetici Yöneticimizin "Yeniden Paylaşıcıdan uyarı yok" kuralı vardır.


1
ReSharper ayarlarınızı değiştirebilirsiniz: P
Bernhard Hofmann

1
Bu kadar kolay olsaydı, Resharper'dan hiç yıpranmadık ... hiç :)
Prankster

1

Değişir, ancak genellikle bu yöntemleri statik yapmam. Kod sürekli değişiyor ve belki bir gün bu işlevi sanal yapmak ve bir alt sınıfta geçersiz kılmak isteyeceğim. Ya da belki bir gün örnek değişkenlerine başvurması gerekecek. Her arama sitesinin değiştirilmesi gerekiyorsa bu değişiklikleri yapmak daha zor olacaktır.


Evet, ama bir gün bunu yapman gerekiyorsa, her zaman durağan hale getirebilirsin. Yoksa bir şey mi kaçırıyorum?
Ray

1
@Ray - Cevabımda bunu kapsıyorum. Statikten statik olmayana büyük bir değişikliktir, bu nedenle tüm tüketicilerin değiştirilmesi gerekir. Küçük bir program için büyük bir sorun değil, ancak başkaları tarafından tüketilecek bir kitaplıksa, bu dikkate alınmalıdır.
Michael

Tüm çağrı sitelerinin statik bir yöntem çağrısından bir üye işlev çağrısına değiştirilmesi gerekir.
Brian Ensink

Üzgünüm, bunu yorumumdan sonra eklediniz. Zihnimde özel yöntemler hakkında düşünüyordum, ancak bu kamusal yöntemler için geçerli bir nokta.
Ray

... ya da bir gün onu atabilirsin. bu argümanlar bir yöntemi durağan yapmam için yeterince iyi değil.
agnieszka

1

Bunu düşünmenin en iyi yolunun şudur: Sınıfın hiçbir örneği anlık olarak geliştirilmediğinde veya bir tür küresel durumu korurken çağrılması gereken bir sınıf yöntemine ihtiyacınız varsa, o zaman statik iyi bir fikirdir. Ancak genel olarak, üyeleri statik olmayan yapmayı tercih etmenizi öneririm.


1

Yöntemlerinizi ve sınıflarınızı düşünmelisiniz:

  • Onları nasıl kullanacaksınız?
  • Kodunuzun farklı seviyelerinden onlara çok sayıda erişime ihtiyacınız var mı?
  • Bu, akla gelebilecek hemen her projede kullanabileceğim bir yöntem / sınıf mı?

Son ikisi 'evet' ise, yönteminizin / sınıfınızın muhtemelen statik olması gerekir.

En çok kullanılan örnek muhtemelen Mathsınıftır. Her ana OO dilinde buna sahiptir ve tüm yöntemler statiktir. Çünkü bunları herhangi bir yerde, herhangi bir zamanda, bir örnek oluşturmadan kullanabilmeniz gerekir.

Bir başka güzel örnek de Reverse()C # 'daki yöntemdir.
Bu, Arraysınıftaki statik bir yöntemdir . Dizinizin sırasını tersine çevirir.

Kod:

public static void Reverse(Array array)

Hiçbir şey döndürmez, diziniz tersine çevrilir, çünkü tüm diziler Array sınıfının örnekleridir.


Math kötü bir örnek. Ben sanırım daha iyi: newnumber = number.round newnumber = Math.round (sayı) den (2)
graffic

3
Math sınıfı, statik sınıfları kullanmanın mükemmel bir örneğidir. Bu konu bununla ilgili, sayıları nasıl yuvarlamayı tercih ettiğinizle ilgili değil ...
KdgDev

1

Yeni yöntemi özel statik hale getirdiğiniz sürece, bu büyük bir değişiklik değildir. Aslında, FxCop bu kılavuzu aşağıdaki bilgilerle birlikte kurallarından biri olarak içerir ( http://msdn.microsoft.com/en-us/library/ms245046(VS.80).aspx ):

Yöntemleri statik olarak işaretledikten sonra, derleyici bu üyelere sanal olmayan arama siteleri yayınlayacaktır. Sanal olmayan arama sitelerinin yayınlanması, geçerli nesne işaretçisinin boş olmadığını garantileyen her arama için çalışma zamanında bir denetimi engeller. Bu, performansa duyarlı kod için ölçülebilir bir performans kazancı sağlayabilir. Bazı durumlarda, mevcut nesne örneğine erişilememesi bir doğruluk sorununu temsil eder.

Bununla birlikte, David Kean'ın ilk yorumu, bunun performans kazanımından çok doğru olmakla ilgili olduğunu söyleyerek endişeleri daha kısa ve öz bir şekilde özetliyor:

Bu kural bir performans sorunu olarak sınıflandırılsa da, bir yöntemi statik hale getirmenin performans artışı yalnızca% 1 civarındadır. Daha ziyade, diğer örnek üyelerini kullanmadaki başarısızlığı nedeniyle üyede bir eksik veya bir hatayı gösterebilecek bir doğruluk sorunudur. Bir yöntemi statik olarak işaretlemek ( Visual Basic'te Paylaşılan ), örnek durumuna dokunmama niyetini netleştirir.


1

Elimden gelen her şeyi kesinlikle farklı bir nedenle statik hale getirirdim:

JIT'deyken statik fonksiyonlar "this" parametresi olmadan çağrılır. Bu, örneğin, 3 parametreli statik olmayan bir işlevin (üye yöntemi) yığın üzerinde 4 parametre ile itildiği anlamına gelir.

Statik bir işlev olarak derlenen aynı işlev, 3 parametre ile çağrılacaktır. Bu, JIT için kayıtları serbest bırakabilir ve yığın alanını koruyabilir ...


1

"Yalnızca özel yöntemleri statik yap" kampındayım. Herkese açık bir yöntem oluşturmak, istemediğiniz birleştirme ortaya çıkarabilir ve test edilebilirliği azaltabilir: Genel statik bir yöntemi saplayamazsınız.

Genel statik bir yöntem kullanan bir yöntemi birim test etmek istiyorsanız, statik yöntemi de test etmiş olursunuz, ki bu istediğiniz şey olmayabilir.


1

Doğası gereği statik olmayan bazı nedenlerle yapılan statik yöntemler can sıkıcıdır. Zekaya:

Bankamı arayıp bakiyemi istiyorum.
Hesap numaramı istiyorlar.
Yeterince adil. Örnek yöntemi.

Bankamı arayıp posta adreslerini soruyorum.
Hesap numaramı istiyorlar.
O NE LAN? Başarısız - statik yöntem olmalıydı.


1
Ya farklı müşterilere farklı şubeler tarafından hizmet verilirse? Yazışmaları bankanın ana ofisine göndermek, sonunda uygun şubeye ulaştırabilir, ancak bu, bir müşteriye kendisine hizmet veren belirli şubenin adresini kullanarak daha iyi hizmet verilemeyeceği anlamına gelmez.
supercat

0

Genel olarak saf fonksiyonların işlevsel bir perspektifinden bakıyorum. Bir örnek yöntemi olması gerekiyor mu? Aksi takdirde, kullanıcıyı değişkenleri aktarmaya zorlamaktan ve mevcut örneğin durumunu bozmaktan faydalanabilirsiniz. (Halen durumu karıştırabilirsiniz, ancak önemli olan, tasarım gereği bunu yapmamaktır.) Genelde genel üyeler olarak örnek metotları tasarlarım ve özel üyeleri statik yapmak için elimden gelenin en iyisini yaparım. Gerekirse (daha sonra bunları diğer sınıflara daha kolay çıkartabilirsiniz.


-1

Bu gibi durumlarda, yöntemi statik veya utils kitaplığına taşıma eğilimindeyim, bu nedenle "nesne" kavramını "sınıf" kavramıyla karıştırmıyorum

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.