निजी स्थैतिक तरीकों का उपयोग करने के लिए लाभ


209

एक ऐसी क्लास बनाते समय जिसमें आंतरिक निजी तरीके होते हैं, आमतौर पर कोड डुप्लीकेशन को कम करने के लिए, जिसे किसी भी उदाहरण फ़ील्ड के उपयोग की आवश्यकता नहीं होती है, क्या विधि को स्थिर घोषित करने के लिए प्रदर्शन या मेमोरी फायदे हैं?

उदाहरण:

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 () विधियों को स्थिर घोषित करने का कोई लाभ है? कोई राय नहीं कृपया, मेरी एक राय है।


जवाबों:


221

से FxCop नियम पेज इस पर:

जब आप विधियों को स्थैतिक के रूप में चिह्नित करते हैं, तो संकलक इन सदस्यों के लिए गैर-आभासी कॉल साइटों का उत्सर्जन करेगा। गैर-आभासी कॉल साइटों को छोड़ने से प्रत्येक कॉल के लिए रनटाइम पर एक चेक को रोका जा सकेगा जो यह सुनिश्चित करता है कि वर्तमान ऑब्जेक्ट पॉइंटर गैर-अशक्त है। इसका परिणाम प्रदर्शन-संवेदनशील कोड के लिए औसत दर्जे का प्रदर्शन हो सकता है। कुछ मामलों में, वर्तमान ऑब्जेक्ट का उपयोग करने में विफलता एक शुद्धता समस्या का प्रतिनिधित्व करती है।


37
मैं यह भी जोड़ूंगा कि "स्थिर" खंड नुकसान नहीं पहुंचाता है और 1 शब्द के साथ पहले से ही कुछ "प्रलेखन" प्रदान करता है। यह आपको बताता है कि यह विधि किसी भी उदाहरण के सदस्य का उपयोग नहीं कर रही है, और आपको यह दस्तावेज़ लगभग मुफ्त में मिलता है
frandevel

20
मैं यहाँ तक कहूँगा: "यदि किसी विधि को राज्य अभिगमन (इस) की आवश्यकता नहीं है, तो इसे सामान्य नियम के रूप में स्थिर करें।"
डैनमैन

3
संतुलन के हितों में, यह इंगित करने योग्य है कि बहुत से लोग आम तौर पर स्थिर तरीकों के खिलाफ होते हैं क्योंकि वे बहुरूपता को तोड़ते हैं, और इसका मतलब है कि परीक्षण के लिए वस्तु को ठोकर नहीं दी जा सकती है। उदाहरण के लिए googletesting.blogspot.co.uk/2008/12/…
एंडी

@ एंडी - अच्छी बात है। लाइन खींचने का एक तरीका यह देखना होगा कि क्या स्थैतिक विधि आपके द्वारा पास किए गए मापदंडों के बाहर कुछ भी एक्सेस कर रही है। जब तक यह इस तरह से स्व-निहित है, तब तक परीक्षण करना आसान होना चाहिए, और इसकी कोई आवश्यकता नहीं है किसी चीज को ठोकर मारना।
नील

4
कई डेवलपर्स "निजी स्थिर" से परिचित नहीं हैं। मैंने अपनी टीम के कॉमन कोड बेस में इसका इस्तेमाल किया है और इससे भ्रम पैदा हुआ है। बदले में, यह बहुत मामूली लाभ प्रदान करता है। हम टीम पर सभी को शिक्षित करने का विकल्प चुन सकते हैं, जिसमें भविष्य के सभी डेवलपर्स कोड को बनाए रखते हैं, जैसा कि इसका मतलब है। लेकिन एक निजी विधि को निजी स्थैतिक में बदलने का लाभ इतना मामूली है (उदाहरण डेटा पर निर्भरता को दूर करना), यह प्रयास और भ्रम के लायक नहीं है। विधि पहले से ही निजी-गुंजाइश है। यह एक ऐसी भाषा है जो वास्तव में जानना आवश्यक नहीं है।
कर्टिस येलोप

93

जब मैं एक क्लास लिख रहा होता हूं, तो ज्यादातर तरीके दो श्रेणियों में गिर जाते हैं:

  • ऐसी विधियाँ जो वर्तमान आवृत्ति की स्थिति का उपयोग / परिवर्तन करती हैं।
  • हेल्पर तरीके जो वर्तमान वस्तु की स्थिति का उपयोग / परिवर्तन नहीं करते हैं, लेकिन मुझे उन मूल्यों की गणना करने में मदद करते हैं जिनकी मुझे कहीं और आवश्यकता है।

स्थैतिक तरीके उपयोगी होते हैं, क्योंकि सिर्फ इसके हस्ताक्षर को देखकर, आप जानते हैं कि यह कॉलिंग वर्तमान उदाहरण की स्थिति का उपयोग या संशोधित नहीं करता है।

इस उदाहरण को लें:

पब्लिक क्लास लाइब्रेरी
{
    निजी स्थिर पुस्तक खोज पुस्तिका (सूची पुस्तक <, पुस्तक> स्ट्रिंग शीर्षक)
    {
        // कोड यहाँ जाता है
    }
}

यदि लाइब्रेरी की स्थिति का एक उदाहरण कभी भी खराब हो जाता है, और मैं यह पता लगाने की कोशिश कर रहा हूं कि, मैं अपने हस्ताक्षर से, केवल खोजपुस्तक को अपराधी के रूप में नियमबद्ध कर सकता हूं।

मैं एक विधि या फ़ंक्शन के हस्ताक्षर के साथ जितना संभव हो उतना कम संवाद करने की कोशिश करता हूं, और ऐसा करने का एक उत्कृष्ट तरीका है।


1
C ++ में कॉन्स्टेंस-मेथड डिक्लेरेशन, क्या यह नहीं है?
अन्हुप्पे

हां - यह एक और अच्छा तरीका है कि भाषा का उपयोग करके चीजों को सरल बनाने के लिए जो गलत हो सकता है उसे सीमित करके।
नील

यह जरूरी सच नहीं है। मान लेते हैं कि किताबों को संग्रहित करने के Libraryलिए इसका एक उदाहरण क्षेत्र List<Book> _booksहै (न कि आप किस Libraryप्रकार वर्ग शायद w / e डिजाइन करेंगे ), और यह इस सूची को पास करता है findBook, और वह स्थैतिक विधि कॉल books.Clear()या अन्य books.Reverse()। यदि आप कुछ परस्पर स्थिति के संदर्भ में एक स्थिर विधि का उपयोग करते हैं, तो वह स्थैतिक विधि आपके राज्य को बहुत अच्छी तरह से गड़बड़ कर सकती है।
सारा

1
सच। और उस स्थिति में, हस्ताक्षर हमें दिखाएगा कि इस पद्धति में लाइब्रेरी का एक उदाहरण (और म्यूट करने की क्षमता) तक पहुंच थी।
नील

वस्तुतः किसी भी सुरक्षात्मक निर्माण के लिए हम इसका उपयोग कर सकते हैं, इसे कम करने का कोई तरीका है। लेकिन उनका उपयोग करना अभी भी बुद्धिमान है और "सफलता के गड्ढे" की ओर, हमें सही दिशा में ले जाने में मदद करता है।
नील

81

स्टैटिक मेथड के लिए एक कॉल Microsoft मध्यवर्ती भाषा (MSIL) में एक कॉल इंस्ट्रक्शन उत्पन्न करता है, जबकि इंस्टेंस मेथड के लिए कॉल एक कॉलवर्ट इंस्ट्रक्शन उत्पन्न करता है, जो एक अशक्त वस्तु संदर्भ के लिए भी जाँच करता है। हालांकि, ज्यादातर समय दोनों के बीच प्रदर्शन अंतर महत्वपूर्ण नहीं होता है।

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


15

हां, संकलक को संकेत thisसूचक को staticविधियों में पारित करने की आवश्यकता नहीं है । यहां तक ​​कि अगर आप इसे अपने उदाहरण विधि में उपयोग नहीं करते हैं, तब भी इसे पारित किया जा रहा है।


यह रनटाइम पर प्रदर्शन या मेमोरी लाभ से कैसे संबंधित है?
स्कॉट डोरमैन

11
एक अतिरिक्त पैरामीटर पास करने का मतलब है कि सीपीयू को उस पैरामीटर को एक रजिस्टर में रखने के लिए अतिरिक्त काम करना होगा, और यदि स्टेक विधि किसी अन्य विधि से कॉल करती है, तो इसे स्टैक पर धक्का दें।
कैंट बूगार्ट

5

यह थोड़ा तेज होगा क्योंकि यह कोई पैरामीटर पारित नहीं हुआ है (हालांकि विधि को कॉल करने की प्रदर्शन लागत शायद इस बचत से बहुत अधिक है)।

मैं सबसे अच्छा कारण कहूंगा कि मैं निजी स्थैतिक तरीकों के बारे में सोच सकता हूं, इसका मतलब है कि आप गलती से ऑब्जेक्ट को बदल नहीं सकते हैं (जैसा कि यह कोई संकेतक नहीं है)।


4

यह आपको याद रखने के लिए मजबूर करता है कि कोई भी क्लास-स्कोप्ड सदस्य घोषित करता है जिसे फ़ंक्शन स्थिर के रूप में भी उपयोग करता है, जो प्रत्येक उदाहरण के लिए उन वस्तुओं को बनाने की स्मृति को सहेजना चाहिए।


सिर्फ इसलिए कि यह एक क्लास-स्कोप्ड वैरिएबल है इसका मतलब यह नहीं है कि यह स्थिर होना चाहिए।
स्कॉट डोरमैन

3
नहीं, लेकिन अगर यह एक स्थिर विधि द्वारा उपयोग किया जाता है तो यह स्थिर होना चाहिए । यदि विधि स्थिर नहीं थी, तो हो सकता है कि आपने कक्षा के सदस्य को स्थिर नहीं बनाया होगा, और इसके परिणामस्वरूप कक्षा के प्रत्येक उदाहरण के लिए अधिक मेमोरी का उपयोग किया जाएगा।
जोएल कोएहॉर्न

2

जब तक वे वास्तव में नहीं हो सकते, मैं सभी निजी तरीकों को स्थिर होना पसंद करता हूं। मैं निम्नलिखित को बहुत पसंद करूंगा:

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;
    }
}

इंस्टेंस फ़ील्ड तक पहुँचने वाली प्रत्येक विधि पर। ऐसा क्यों है? क्योंकि गणना की यह प्रक्रिया अधिक जटिल हो जाती है और कक्षा 15 निजी सहायक विधियों के साथ समाप्त हो जाती है, तो मैं वास्तव में उन्हें एक नए वर्ग में खींचना चाहता हूं जो कि एक अर्थपूर्ण तरीके से चरणों के एक सबसेट को कूटबद्ध करता है।

जब MyClassअधिक निर्भरता हो जाती है क्योंकि हमें लॉगिंग की आवश्यकता होती है और वेब सेवा को सूचित करने की भी आवश्यकता होती है (कृपया क्लिच उदाहरणों का बहाना करें), तो वास्तव में यह देखने में मददगार है कि कौन सी विधियां निर्भर करती हैं।

R # जैसे उपकरण आपको कुछ कीस्ट्रोक्स में निजी स्थिर विधियों के सेट से एक कक्षा निकालने की सुविधा देते हैं। इसे करने का प्रयास करें जब सभी निजी सहायक विधियाँ कसकर उदाहरण के क्षेत्र में युग्मित हो जाती हैं और आप देखेंगे कि यह काफी सिरदर्द हो सकता है।


-3

जैसा कि पहले ही कहा गया है, स्थैतिक तरीकों के कई फायदे हैं। तथापि; ध्यान रखें कि वे आवेदन के जीवन के लिए ढेर पर रहेंगे। मैंने हाल ही में एक विंडोज़ सेवा में एक मेमोरी लीक को ट्रैक करने में एक दिन बिताया ... रिसाव एक वर्ग के अंदर निजी स्थैतिक तरीकों के कारण हुआ, जिसने आईडीसोपायरी को लागू किया और लगातार उपयोग करने वाले बयान से बुलाया गया। हर बार जब यह वर्ग बनाया गया था, तो स्मृति को कक्षा के भीतर स्थिर तरीकों के लिए ढेर पर आरक्षित किया गया था, दुर्भाग्य से, जब कक्षा का निपटान किया गया था, तब स्थिर तरीकों के लिए मेमोरी जारी नहीं की गई थी। यह इस सेवा के मेमोरी फ़ुटप्रिंट के कारण पूर्वानुमानित परिणामों के साथ कुछ दिनों के भीतर सर्वर की उपलब्ध मेमोरी का उपभोग करता है।


4
इसका कोई मतलब नहीं है। ढेर कभी किसी भी तरीके के लिए मेमोरी को स्टोर नहीं करता है , स्थिर या अन्यथा। ढेर वस्तु उदाहरणों के लिए है। किसी भी विधि के किसी भी आह्वान के लिए स्टैक पर डेटा होगा (मापदंडों के लिए मेमोरी को होल्ड करने के लिए, वैल्यू, नॉन-होव्ड लोकल, इत्यादि) लेकिन यह सब उस समय खत्म हो जाता है जब विधि निष्पादित होती है।
सर्व
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.