Yöntem statik hale getirilebilir, ama olmalı mı?


366

Resharper, asp.net sayfası başına statik hale getirilebilecek birden fazla işlevi belirtmeyi sever. Onları statik hale getirirsem bana yardımcı olur mu? Onları statik hale getirmeli ve bir yardımcı sınıfa taşımalı mıyım?


20
Resharper aslında "düşük uyum, düşük uyum" diye bağırmıyor mu? yöntemin gerçekten bu sınıfa ait olup olmadığına bakmanın zamanı geldi.
PK

Yanıtlar:


245

Statik yöntemlere karşı Örnek yöntemleri
10.2.5 C # Dil Spesifikasyonunun statik ve örnek üyeleri arasındaki farkı açıklar. Genel olarak, statik yöntemler örnek yöntemleri üzerinde çok küçük bir performans artışı sağlayabilir, ancak yalnızca aşırı durumlarda ( bu konu hakkında daha fazla ayrıntı için bu cevaba bakınız ).

FxCop veya Kod Analizindeki CA1822 kuralı şunları belirtir:

"[Üyeleri statik olarak işaretleme] 'den sonra, derleyici bu üyelere sanal olmayan çağrı siteleri yayar, bu da geçerli nesne işaretçisinin boş olmamasını sağlayan her çağrı için çalışma zamanında bir denetimi engeller. Bu, ölçülebilir bir performans kazancı ile sonuçlanabilir. Bazı durumlarda, geçerli nesne örneğine erişilememesi bir doğruluk sorununu temsil eder. "

Fayda Sınıfı
Tasarımınızda bir anlam ifade etmedikçe bunları bir fay sınıfına taşımamalısınız. Statik yöntem, belirli bir ToRadians(double degrees)türle ilişkiliyse , tıpkı bir yöntem, açıları temsil eden bir sınıfla ilgili ise, bu yöntemin bu türün statik bir üyesi olarak var olması mantıklıdır (not, bu, gösterim amacıyla kıvrık bir örnektir).


2
> derleyici bu üyelere sanal olmayan çağrı siteleri yayar. Aslında "derleyici yayabilir ...". Bazı potansiyel hata etrafında çalışmak için çağrı yerine callvirt kullanarak C # derleyici hakkında bir şey hatırlıyorum.
Jonathan Allen

24
Doğrudan FxCop 1.36'dan kesip yapıştırdım. FxCop yanlışsa, yeterince adil.
Jeff Yates

5
@Maxim "Saçmalık" ifadesini takdir ettiğimden emin değilim; yabancılara yaklaşım oldukça kaba bir yol. Ancak, temel nokta geçerlidir; Bazı şeyleri biraz güncelledim (9 yıl önceydi, bu yüzden orijinal iddiamın temelini hatırlamıyorum).
Jeff Yates

10
@Maxim Puanınız geçersiz. 9 yıl önce iyi bir not almadım. Hataları işaret eden yorumları (veya hataları düzelten) takdir ediyorum, ancak başkalarına karşı kaba ve mantıksız beklentiler koymayın. Bir şeye "saçmalık" deme; iyilik hatası ya da cehaletine karşı dürüst olmaktan ziyade aldatma niyeti anlamına gelir. Bu kaba. Burada yardım etmek için zaman ayırıyorum ve saygısızlıkla tedavi edildiğinde gerçekten anlamsız geliyor. Bana neyin kırılacağını söyleme - bu benim seçimim, senin değil. Saygı ve dürüstlüğe nasıl dikkat çekeceğinizi öğrenin. Teşekkür ederim.
Jeff Yates

2
@Maxim Delegeler her örneğin yanında depolanmazken, vatansız bir sınıfın her bir örneği gerçekten yığın üzerinde bir miktar yer kaplar; Genellikle hizmetleri başlatmak bir uygulamadaki sıcak yol değildir, ancak uygulamanız bu nesnelerin çoğunu oluşturuyorsa, sadece statik yöntemler kullanılarak önlenebilecek GC basıncı oluşturacaktır. OP'nin, aşırı durumlarda statik yöntemlerin vatansız örneklere göre bir performans avantajı sağladığı orijinal iddiası, uygun bir şekilde nüanslı ve geçerliydi.
Asad Saeeduddin

259

Bence performans, ad alanı kirliliği vb. Kendinize neyin mantıklı olduğunu sorun. Yöntem mantıksal olarak türün bir örneğinde mi çalışıyor, yoksa türün kendisiyle mi ilgili? İkincisi ise, statik bir yöntem yapın. Bunu yalnızca kontrolünüz altında olmayan bir türle ilgiliyse bir yardımcı program sınıfına taşıyın.

Bazen bir örnek üzerinde mantıksal olarak hareket eden ancak henüz örnek durumundan herhangi birini kullanmayan yöntemler vardır . Örneğin, bir dosya sistemi oluşturuyorsanız ve bir dizin kavramına sahip olsaydınız, ancak bunu henüz uygulamadıysanız, dosya sistemi nesnesinin türünü döndüren bir özellik yazabilirsiniz ve her zaman sadece "file" - ancak mantıksal olarak örnekle ilişkilidir ve bu nedenle bir örnek yöntemi olmalıdır. Bu, yöntemi sanal yapmak istiyorsanız da önemlidir - özel uygulamanızın herhangi bir duruma ihtiyacı olmayabilir, ancak türetilmiş sınıflar gerekebilir. (Örneğin, bir koleksiyona salt okunur olup olmadığını sorma - henüz bu koleksiyonun salt okunur bir formunu uygulamamış olabilirsiniz, ancak açıkça türün değil, koleksiyonun bir özelliğidir.)


1
İyi bir linterın sanal olmayan yöntemlerle mesajı kısıtlama seçeneği olması gerektiğini düşünürdüm, çünkü temel sınıf yönteminin pratikte hiçbir şey yapmaması çok yaygın olurdu. Geçersiz kılma yöntemleri her zaman değil, genellikle bir şeyler yapar. Bazen, yöntemleri esas olarak örneği yok sayan, ancak örneğin kullanılacak doğru yöntemi seçmek için gerekli olan boş bir iEnumerable gibi bir şey için bir sınıfa sahip olmak yararlı olabilir.
supercat

2
"Bazen bir örnek üzerinde mantıksal olarak hareket eden ancak henüz örnek durumundan herhangi birini kullanmayan yöntemler vardır. Örneğin," bu örnekte "örneğin" kullanımından keyif aldım.
PaulBinder

56

Bir yöntemi staticsınıf içinde işaretlemek , kodun gözden geçirilmesi sırasında bilinmesi yararlı olabilecek hiçbir örnek üyesi kullanmadığını açıkça gösterir.

Bu kadar yakından ilişkili, kavram açısından başka bir sınıf tarafından paylaşılmak istenmediği sürece, onu başka bir sınıfa taşımak zorunda değilsiniz.


22

Eminim bu senin durumda değil, ama bir "kötü koku" Ben bazı kodda gördüm ben bir sürü statik yöntemlerin bir heck kullanılan korunarak acı vardı.

Ne yazık ki, bunlar belirli bir uygulama durumunu kabul eden statik yöntemlerdir. (neden emin, uygulama başına sadece bir kullanıcı olacak! Kullanıcı sınıfı neden statik değişkenlerde bunu takip etmiyor?) Küresel değişkenlere erişmenin yüceltilmiş yollarıydı. Ayrıca neredeyse her zaman kötü bir fikir olan statik yapıcıları (!) Vardı. (Birkaç makul istisna olduğunu biliyorum).

Bununla birlikte, statik yöntemler, aslında nesnenin bir örneğinin durumuna bağlı olmayan etki alanı mantığını dışladığında oldukça kullanışlıdır. Kodunuzu çok daha okunabilir hale getirebilirler.

Onları doğru yere koyduğunuzdan emin olun. Statik yöntemler müdahaleci olarak diğer nesnelerin iç durumunu değiştiriyor mu? Davranışlarının bunun yerine bu sınıflardan birine ait olduğu iyi bir dava yapılabilir mi? Endişeleri doğru şekilde ayırmıyorsanız, daha sonra baş ağrısına girebilirsiniz.


4
Sorununuz statik yöntemlerle değil, statik alanlarla / özelliklerle ilgilidir.
Asad Saeeduddin

10

Bu ilginç bir okuma:

http://thecuttingledge.com/?p=57

ReSharper aslında yönteminizi statik hale getirmenizi önermez. Kendinize, bu yöntemin imzasında görünen sınıflardan birinin aksine, neden bu sınıfta olduğunu sormalısınız ...

ancak yeniden düzenleyici belgesel şöyle diyor: http://confluence.jetbrains.net/display/ReSharper/Member+can+be+made+static


2
Bence bu noktanın hafife alınması. Aracın size gerçekten söylediği şey, yöntemin yalnızca başka bir sınıfın üyeleri üzerinde çalıştığıdır. Bir tür komut (veya "kullanım örneği" veya "etkileşimci") nesnesiyse, kimin sorumluluğu diğer nesneleri manipüle etmektir, sorun değil. Ancak, yalnızca gibi bir çok geliyor tek diğer sınıf işliyorsa, Özelliği Envy .
Greg

9

Sadece @Jason True'un cevabına eklemek için , bir yönteme 'statik' koymanın, yöntemin 'saf' olacağını garanti etmediğini fark etmek önemlidir. Bildirildiği sınıfa göre vatansız olacaktır, ancak durumu olan diğer 'statik' nesnelere (uygulama yapılandırması vb.) De erişebilir, bu her zaman kötü bir şey olmayabilir, ancak Ben şahsen statik yöntemleri tercih etme eğilimindeyim, eğer saflarsa, çevredeki durum hakkında endişelenmenize gerek kalmadan, onları tek tek test edebilir ve onlarla ilgili akıl yürütebilirsiniz.


6

Belirli bir senaryoda en okunabilir ve sezgisel olanı yapmalısınız.

Performans argümanı, en aşırı durumlar dışında iyi bir şey değildir, çünkü gerçekte olan tek şey, bir ekstra parametrenin ( this) örneğin yöntemler için yığına doğru itilmesidir.


6

Bir sınıf içindeki karmaşık mantık için, örnek girişlerinin yöntem imzasında açıkça tanımlandığı ve hiçbir örnek yan etkisinin meydana gelmediği yalıtılmış mantık oluştururken yararlı özel statik yöntemler buldum. Tüm çıkışlar dönüş değeri veya çıkış / ref parametreleri aracılığıyla olmalıdır. Karmaşık mantığı yan etkisiz kod bloklarına ayırma , kodun okunabilirliğini ve geliştirme ekibinin buna olan güvenini artırabilir.

Öte yandan, fayda yöntemlerinin çoğalmasıyla kirlenen bir sınıfa yol açabilir. Her zaman olduğu gibi, mantıksal adlandırma, dokümantasyon ve takım kodlama sözleşmelerinin tutarlı bir şekilde uygulanması bunu hafifletebilir.


5

ReSharper mantığı kontrol etmez. Yalnızca yöntemin örnek üyelerini kullanıp kullanmadığını denetler. Yöntem özelse ve yalnızca (belki yalnızca bir tane) örnek yöntemi tarafından çağrılırsa, bu bir örnek yöntemine izin vermek için kullanılan bir işarettir.


3

İşlevler birçok sayfada paylaşılıyorsa, bunları bir temel sayfa sınıfına koyabilir ve daha sonra bu işlevselliği kullanan tüm asp.net sayfalarından devralınmasını sağlayabilirsiniz (ve işlevler yine de statik olabilir).


3

Bir yöntemi statik yapmak, ilk önce o sınıfın bir örneğini oluşturmadan yöntemi sınıfın dışından çağırabileceğiniz anlamına gelir. Bu, üçüncü taraf satıcı nesneleri veya eklentileriyle çalışırken faydalıdır. Con.Writeline () öğesini çağırmadan önce bir "con" Konsolu nesnesi oluşturmanız gerekip gerekmediğini düşünün;


Java, con.Writeline () öğesini çağırmadan önce Console nesnesini oluşturmak için bir fabrika örneği oluşturmanızı sağlar.
ScottMichaud

2

İsim alanı kirliliğini kontrol etmeye yardımcı olur.


8
Bir yöntemi statik yapmak ad alanı kirliliğini önlemeye nasıl yardımcı olur?
lockstock

1
Deneyimden, yöntemleri statik yöntemlerle sınıflara ayırarak, diğer kitaplık veya yerleşik işlevlerle çakışabilecek tüm gevşek işlevlerin "yakalama torbasının" ön ekini kullanmak zorunda kalmıyorsunuz. Statik yöntemlerle, etkili bir şekilde Sınıf adı altında adlandırılırlar, ör. Class.a_core_function( .. )vsa_core_function( .. )
lintuxvi

0

Sadece benim tuppence: Tüm paylaşılan statik yöntemleri bir yardımcı program sınıfına eklemek,

using static className; 

kodunuzu daha hızlı yazmanızı ve okumayı daha kolay hale getiren kullanım ifadelerinize ekleyin. Örneğin, devralınan bazı kodda "küresel değişkenler" olarak adlandırılacak çok sayıda var. Örnek sınıf olan bir sınıfta global değişkenler yapmak yerine, hepsini bir global sınıfın statik özellikleri olarak ayarladım. İşi, dağınık ise yapar ve ben zaten başvurulan statik ad alanı var çünkü özellikleri adıyla başvurabilirsiniz.

Bunun iyi bir uygulama olup olmadığı hakkında hiçbir fikrim yok. Ben sadece # Roselyn ipuçları bana rehberlik izin çalışıyorum C # 4/5 ve refactor için çok eski kod hakkında bilgi edinmek için var.

Joey


0

Umarım, statik ve örnek yöntemler arasındaki farkı zaten anlamışsınızdır. Ayrıca, uzun bir cevap ve kısa bir cevap da olabilir. Uzun cevaplar zaten başkaları tarafından verilmektedir.

Kısa cevabım: Evet, Resharper'ın önerdiği gibi bunları statik yöntemlere dönüştürebilirsiniz. Bunu yapmanın hiçbir zararı yoktur. Bunun yerine, yöntemi statik hale getirerek, aslında yöntemi koruyorsunuz, böylece gereksiz yere herhangi bir örnek üyesini bu yönteme kaydırmazsınız. Bu şekilde, " Sınıfların ve üyelerin erişilebilirliğini en aza indirin .

ReSharper, bir örnek yönteminin statik bir yönteme dönüştürülebileceğini öne sürdüğünde, aslında size "Neden .. bu yöntem, durumlarından hiçbirini kullanmadığı için bu sınıfta oturuyor?" Size düşünce için yiyecek verir. Daha sonra, bu yöntemi statik bir yardımcı sınıfa taşıma ihtiyacını anlayan sizsiniz. SOLID ilkelerine göre, bir sınıfın sadece bir temel sorumluluğu olmalıdır. Böylece, sınıflarınızı daha iyi bir şekilde temizleyebilirsiniz. Bazen, örnek sınıfınızda bile bazı yardımcı yöntemlere ihtiyacınız olabilir. Bu durumda, bunları #region yardımcısı içinde tutabilirsiniz.

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.