Özel Statik Yöntemleri Kullanmanın Avantajları


209

Dahili özel yöntemlere sahip bir sınıf oluştururken, genellikle kod çoğaltmasını azaltmak için, herhangi bir örnek alanının kullanılmasını gerektirmeyen bir sınıf oluştururken, yöntemi statik olarak bildirmenin performans veya bellek avantajları var mı?

Misal:

foreach (XmlElement element in xmlDoc.DocumentElement.SelectNodes("sample"))
{
    string first = GetInnerXml(element, ".//first");
    string second = GetInnerXml(element, ".//second");
    string third = GetInnerXml(element, ".//third");
}

...

private static string GetInnerXml(XmlElement element, string nodeName)
{
    return GetInnerXml(element, nodeName, null);
}

private static string GetInnerXml(XmlElement element, string nodeName, string defaultValue)
{
    XmlNode node = element.SelectSingleNode(nodeName);
    return node == null ? defaultValue : node.InnerXml;
}

GetInnerXml () yöntemlerini statik olarak bildirmenin bir avantajı var mı? Görüş yok, lütfen bir fikrim var.


Yanıtlar:


221

Gönderen FxCop kural sayfasında bu konuda:

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


37
Ayrıca "statik" bir cümle zarar vermez ve zaten 1 kelime ile bazı "belgeler" sağlar. Size bu yöntemin herhangi bir örnek üye kullanmadığını ve bu belgeyi neredeyse ücretsiz olarak
aldığınızı söyler

20
Ben genel bir kural olarak "bir yöntem devlet erişimi (bu), statik olun" demek gibi ileri gitmek istiyorum.
DanMan

3
Dengenin çıkarları açısından, birçok insanın genel olarak statik yöntemlere karşı olduğunu, çünkü polimorfizmi bozduğunu ve nesnenin test için inatlanamayacağı anlamına geldiğini belirtmek gerekir. örneğin bkz. googletesting.blogspot.co.uk/2008/12/…
Andy

@ Andy - İyi nokta. Çizgiyi çizmenin bir yolu, statik yöntemin geçirdiğiniz parametrelerin dışındaki herhangi bir şeye erişip erişmediğine bakmak olacaktır. Bu şekilde kendi kendine yeten olduğu sürece, test edilmesi kolay olmalı ve gerek yoktur bir şey saplamak.
Neil

4
Birçok geliştirici "özel statik" bilgisine sahip değildir. Ekibimin ortak kod tabanında kullandım ve karışıklığa neden oldu. Buna karşılık, çok az fayda sağlar. Koddaki gelecekteki tüm geliştiriciler de dahil olmak üzere, takımdaki herkesi ne anlama geldiği konusunda eğitmeyi seçebiliriz. Ancak özel bir yöntemi özel bir statik haline getirmenin yararı o kadar küçüktür (yani örnek verilere bağımlılığı kaldırmak), çabaya ve karışıklığa değmez. Yöntem zaten her iki durumda da özel kapsamdır. Bilmesi gereken bir dil sorunudur.
Curtis Yallop

93

Bir sınıf yazarken, çoğu yöntem iki kategoriye ayrılır:

  • Geçerli örneğin durumunu kullanan / değiştiren yöntemler.
  • Geçerli nesnenin durumunu kullanmayan / değiştirmeyen, ancak başka bir yerde ihtiyacım olan değerleri hesaplamama yardımcı olan yardımcı yöntemler.

Statik yöntemler kullanışlıdır, çünkü yalnızca imzasına bakarak, çağrının geçerli örneğin durumunu kullanmadığını veya değiştirmediğini bilirsiniz.

Bu örneği ele alalım:

genel sınıf Kütüphanesi
{
    özel statik Kitap findBook (Liste <Book> kitaplar, dize başlığı)
    {
        // kod buraya geliyor
    }
}

Eğer bir kütüphane durumunun bir örneği mahvolursa ve nedenini anlamaya çalışıyorum, findBook'u sadece imzasından suçlu olarak çıkarabilirim.

Bir yöntem veya işlevin imzası ile mümkün olduğunca iletişim kurmaya çalışıyorum ve bu bunu yapmanın mükemmel bir yoludur.


1
C ++ 'da const yöntem bildirimi tür, değil mi?
Mart'ta anhoppe

Evet - bu, neyin yanlış gidebileceğini sınırlandırarak işleri basitleştirmek için dili kullanmanın iyi bir yoludur.
Neil

Bu mutlaka doğru değildir. En bir düşünelim Librarybir örnek alanı vardır List<Book> _books(bir tasarım istiyorum değil nasıl 's kitaplarını saklamak için Librarymuhtemelen ama w / e sınıfı) ve bu listeyi geçer findBookve bu statik yöntem çağrıları books.Clear()veya books.Reverse()vb. Değişken bir duruma referansa statik bir yöntem erişimi verirseniz, bu statik yöntem durumunuzu çok iyi bozabilir.
sara

1
Doğru. Ve bu durumda, imza bize bu yöntemin bir Library örneğine erişebildiğini (ve değiştirebildiğini) gösterir.
Neil

Kullanabileceğimiz neredeyse tüm koruyucu yapılar için, onu zayıflatmanın bir yolu var. Ama onları kullanmak hala akıllıca ve bize doğru yönde, "başarı çukuru" doğru itmeye yardımcı olur.
Neil

81

Statik bir yönteme yapılan çağrı, Microsoft ara dilinde (MSIL) bir çağrı yönergesi oluştururken, bir örnek yöntemine yapılan çağrı, boş bir nesne başvurusunu da denetleyen bir callvirt yönergesi oluşturur. Bununla birlikte, çoğu zaman ikisi arasındaki performans farkı önemli değildir.

src: MSDN - http://msdn.microsoft.com/tr-tr/library/79b3xss3(v=vs.110).aspx


15

Evet, derleyicinin örtük thisişaretçiyi staticyöntemlere geçirmesi gerekmez . Örnek yönteminizde kullanmasanız bile, hala geçiyor.


Bu, çalışma zamanında bir performans veya bellek avantajı ile nasıl ilişkilidir?
Scott Dorman

11
Fazladan bir parametre iletilmesi, CPU'nun bu parametreyi bir kayıt defterine yerleştirmek için fazladan iş yapması ve örnek yöntemi başka bir yönteme çağırırsa yığının üzerine itmesi gerektiği anlamına gelir.
Kent Boogaart

5

Bu parametre iletilmediğinden biraz daha hızlı olacaktır (yöntemi çağırmanın performans maliyeti muhtemelen bu tasarruftan önemli ölçüde daha fazladır).

Özel statik yöntemler için düşünebilmemin en iyi nedeninin, nesneyi yanlışlıkla değiştiremeyeceğiniz anlamına geldiği söylenebilir (bu işaretçi olmadığı için).


4

Bu, işlevin kullandığı sınıf kapsamındaki üyeleri de statik olarak bildirmeyi hatırlamaya zorlar, bu da her örnek için bu öğeleri oluşturma belleğini kaydetmelidir.


Sınıf kapsamındaki bir değişken olması statik olması gerektiği anlamına gelmez.
Scott Dorman

3
Hayır, ancak statik bir yöntemle kullanılıyorsa statik OLMALIDIR . Yöntem statik değilse, sınıf üyesini statik yapmamış olabilirsiniz ve bu, sınıfın her örneği için daha fazla bellek kullanılmasına neden olabilir.
Joel Coehoorn

2

Gerçekten olamadıkları sürece tüm özel yöntemlerin statik olmasını çok tercih ederim. Aşağıdakileri çok tercih ederim:

public class MyClass
{
    private readonly MyDependency _dependency;

    public MyClass(MyDependency dependency)
    {
        _dependency = dependency;
    }

    public int CalculateHardStuff()
    {
        var intermediate = StepOne(_dependency);
        return StepTwo(intermediate);
    }

    private static int StepOne(MyDependency dependency)
    {
        return dependency.GetFirst3Primes().Sum();
    }

    private static int StepTwo(int intermediate)
    {
        return (intermediate + 5)/4;
    }
}

public class MyDependency
{
    public IEnumerable<int> GetFirst3Primes()
    {
        yield return 2;
        yield return 3;
        yield return 5;
    }
}

örnek alanına erişen her yöntemin üzerinde. Bu neden? Bu hesaplama süreci daha karmaşık hale geldiğinden ve sınıf 15 özel yardımcı yöntemle sona erdiğinden, GERÇEKTEN onları adımları anlamsal olarak anlamlı bir şekilde içine alan yeni bir sınıfa çekebilmek istiyorum.

Daha MyClassfazla bağımlılık olduğunda, günlüğe kaydetmeye ihtiyacımız olduğu ve ayrıca bir web hizmetini bilgilendirmemiz gerektiğinde (lütfen klişe örneklerini affedin), o zaman hangi yöntemlerin hangi bağımlılıklara sahip olduğunu kolayca görmek gerçekten yararlıdır.

R # gibi araçlar, birkaç tuş vuruşunda bir dizi özel statik yöntemden bir sınıf çıkarmanızı sağlar. Tüm özel yardımcı yöntemler örnek alanına sıkıca bağlandığında bunu deneyin ve bunun oldukça baş ağrısı olabileceğini göreceksiniz.


-3

Daha önce de belirtildiği gibi, statik yöntemlerin birçok avantajı vardır. Ancak; uygulamanın ömrü boyunca yığın üzerinde yaşayacaklarını unutmayın. Geçenlerde bir Windows Hizmetinde bir bellek sızıntısını izlemek için bir gün geçirdim ... sızıntı, IDisposable'ı uygulayan ve sürekli olarak bir kullanım ifadesinden çağrılan bir sınıf içindeki özel statik yöntemlerden kaynaklandı. Bu sınıf her oluşturulduğunda bellek, sınıftaki statik yöntemler için öbek üzerinde ayrıldı, maalesef, sınıf atıldığında, statik yöntemlerin belleği serbest bırakılmadı. Bu, bu hizmetin bellek ayak izinin, tahmin edilebilir sonuçlarla birkaç gün içinde sunucunun kullanılabilir belleğini tüketmesine neden oldu.


4
Bu hiç mantıklı değil. Yığın hiçbir zaman kodun hafızasını statik veya başka bir yöntemle depolamaz . Yığın nesne örnekleri içindir. Herhangi bir yöntemin herhangi bir çağrılması için (parametreler, dönüş değeri, kaldırılmamış yerel ayarlar, vb. İçin belleği tutmak) yığın üzerinde veriler olacaktır, ancak yöntemin yürütülmesi bittiğinde bunların tümü kaybolur.
Servy
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.