विधि को स्थिर बनाया जा सकता है, लेकिन क्या यह होना चाहिए?


366

Resharper प्रति asp.net पृष्ठ पर कई फ़ंक्शन को इंगित करना पसंद करता है जिसे स्थिर बनाया जा सकता है। अगर मैं उन्हें स्थिर कर दूं तो क्या यह मेरी मदद करता है? क्या मुझे उन्हें स्थिर करना चाहिए और उन्हें उपयोगिता वर्ग में ले जाना चाहिए?


20
क्या Resharper वास्तव में "कम-सामंजस्य, कम-सामंजस्य" चिल्ला नहीं रहा है? यह देखने का समय है कि क्या विधि वास्तव में उस वर्ग की है।
पीके

जवाबों:


245

इंस्टेंट तरीके बनाम इंस्टेंस विधियाँ
10.2.5 स्टेटिक और C # लैंग्वेज स्पेसिफिकेशन के उदाहरण सदस्य अंतर बताते हैं। आम तौर पर, स्थैतिक विधियाँ उदाहरण के तरीकों पर बहुत कम प्रदर्शन वृद्धि प्रदान कर सकती हैं, लेकिन केवल कुछ चरम स्थितियों में (इसके बारे में कुछ और विवरणों के लिए इस उत्तर को देखें)।

FxCop या कोड विश्लेषण राज्यों में नियम CA1822:

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

उपयोगिता वर्ग
आपको उन्हें तब तक उपयोगिता वर्ग में नहीं ले जाना चाहिए, जब तक कि यह आपके डिजाइन में समझ में न आए। यदि स्थैतिक विधि एक विशेष प्रकार से संबंधित है, जैसे ToRadians(double degrees)कि एक वर्ग कोणों का प्रतिनिधित्व करने वाले वर्ग से संबंधित है, तो यह उस विधि के उस प्रकार के स्थिर सदस्य के रूप में मौजूद होने के लिए समझ में आता है (नोट, यह प्रदर्शन के उद्देश्यों के लिए एक दृढ़ उदाहरण है)।


2
> संकलक इन सदस्यों को गैर-आभासी कॉल साइटों का उत्सर्जन करेगा वास्तव में यह है कि "संकलक उत्सर्जन कर सकता है ..."। मुझे कुछ संभावित बग के चारों ओर काम करने के लिए कॉल के बजाय कॉलविर्ट का उपयोग करके सी # संकलक के बारे में कुछ याद है।
जोनाथन एलन

24
मैंने इसे FxCop 1.36 से सीधे कट और पेस्ट किया। अगर FxCop गलत है, तो पर्याप्त है।
जेफ येट्स

5
@ मैक्सिम यकीन नहीं है कि मैं "बकवास" बयान की सराहना करता हूं; अजनबियों से संपर्क करने का बहुत अशिष्ट तरीका। हालांकि, अंतर्निहित बिंदु वैध है; मैंने चीजों को थोड़ा अपडेट किया है (यह 9 साल पहले था, इसलिए मुझे अपने मूल दावे की नींव याद नहीं है)।
जेफ़ येट्स

10
@Maxim आपकी बात अमान्य है। मैं आपको विश्वास दिलाता हूं कि मेरी 9 साल पहले अच्छी रेटिंग नहीं थी। मैं उन टिप्पणियों की सराहना करता हूं जो गलतियों को इंगित करती हैं (या उन्हें ठीक करने वाले संपादन), लेकिन असभ्य मत बनो और न ही दूसरों पर अनुचित अपेक्षाएं रखो। "बुलशिट" को कुछ मत कहो; इसका मतलब यह है कि अच्छाई की गलती या अज्ञानता के लिए ईमानदार के बजाय धोखा देने का इरादा है। यह कठोर है। मैं यहां मदद करने के लिए अपना समय स्वेच्छा से देता हूं और जब यह अनादर के साथ व्यवहार किया जाता है तो यह वास्तव में व्यर्थ लगता है। मुझे यह मत बताना कि किस बात से नाराज होना है - यह मेरी पसंद है, तुम्हारी नहीं। सम्मान और अखंडता के साथ अपनी बात बनाना सीखें। धन्यवाद।
जेफ येट्स

2
@Maxim जबकि प्रतिनिधियों को प्रत्येक उदाहरण के साथ संग्रहीत नहीं किया जाता है, लेकिन एक स्टेटलेस क्लास का प्रत्येक उदाहरण वास्तव में ढेर पर कुछ मेमोरी पर कब्जा कर लेता है, जो बेकार उपरि है। आमतौर पर इंस्टेंटिअटिंग सेवाएं किसी एप्लिकेशन में हॉट पाथ नहीं होती हैं, लेकिन यदि आपका एप्लिकेशन इन वस्तुओं का निर्माण करता है, तो यह जीसी प्रेशर का निर्माण करने वाला होता है, जिसे केवल स्थैतिक तरीकों का उपयोग करके टाला जा सकता है। ओपी का मूल दावा है, कि चरम स्थितियों में स्थिर तरीके स्टेटलेस इंस्टेंस पर एक प्रदर्शन लाभ प्रदान करते हैं, उचित रूप से बारीक और वैध थे।
असद सईदुद्दीन

259

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

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


1
मुझे लगता है कि एक अच्छे लिंटर में संदेश को गैर-आभासी तरीकों तक सीमित रखने का विकल्प होना चाहिए, क्योंकि यह बेस-क्लास पद्धति के लिए व्यावहारिक रूप से कुछ भी नहीं करने के लिए बहुत आम होगा। ओवरराइड विधियां आमतौर पर कुछ करेंगी, लेकिन हमेशा नहीं। कभी-कभी एक खाली iEnumerable जैसी किसी चीज के लिए एक वर्ग होना उपयोगी होता है, जिसके तरीके अनिवार्य रूप से उदाहरण को अनदेखा करते हैं, लेकिन जहां उपयोग करने के लिए सही विधि का चयन करना आवश्यक है।
Supercat

2
"कभी-कभी ऐसे तरीके होते हैं जो तार्किक रूप से एक उदाहरण पर कार्य करते हैं लेकिन अभी तक किसी भी उदाहरण की स्थिति का उपयोग करने के लिए नहीं होते हैं। उदाहरण के लिए" मैंने इस उदाहरण में "उदाहरण के लिए" आपके उपयोग का आनंद लिया।
पॉलबिंदर

56

एक विधि को staticएक वर्ग के भीतर चिह्नित करना यह स्पष्ट करता है कि यह किसी भी उदाहरण के सदस्यों का उपयोग नहीं करता है, जो कोड के माध्यम से स्किमिंग करते समय यह जानने में मददगार हो सकता है।

जरूरी नहीं कि आप इसे दूसरी कक्षा में ले जाएं, जब तक कि इसे किसी अन्य वर्ग द्वारा साझा करने का मतलब नहीं है जो कि केवल निकट से जुड़ा हुआ है, अवधारणा-वार।


22

मुझे यकीन है कि यह आपके मामले में नहीं हो रहा है, लेकिन एक "खराब गंध" जो मैंने कुछ कोड में देखा है, मुझे बहुत सारे स्थिर तरीकों की एक बिल्ली को बनाए रखने के माध्यम से भुगतना पड़ा है।

दुर्भाग्य से, वे स्थिर विधियाँ थीं जिन्होंने एक विशेष अनुप्रयोग स्थिति ग्रहण की। (क्यों निश्चित है, हमारे पास प्रति एप्लिकेशन केवल एक उपयोगकर्ता होगा! उपयोगकर्ता वर्ग के पास स्थिर चर में उस पर नज़र रखने की आवश्यकता क्यों नहीं है?) वे वैश्विक चर तक पहुंचने के शानदार तरीके थे। उनके पास स्थिर निर्माता (!) भी थे, जो लगभग हमेशा एक बुरा विचार हैं। (मुझे पता है कि कुछ अपवाद हैं)।

हालाँकि, स्थैतिक विधियाँ काफी उपयोगी होती हैं जब वे डोमेन-लॉजिक को प्रभावित करते हैं जो वास्तव में ऑब्जेक्ट के उदाहरण पर निर्भर नहीं करता है। वे आपके कोड को बहुत अधिक पठनीय बना सकते हैं।

बस सुनिश्चित करें कि आप उन्हें सही जगह पर रख रहे हैं। क्या स्थैतिक विधियाँ अन्य वस्तुओं की आंतरिक स्थिति में आंतरिक रूप से हेरफेर कर रही हैं? क्या एक अच्छा मामला यह बनाया जा सकता है कि उनका व्यवहार उन वर्गों में से एक के बजाय है? यदि आप चिंताओं को ठीक से अलग नहीं कर रहे हैं, तो आप बाद में सिरदर्द के लिए हो सकते हैं।


4
आपकी समस्या स्थैतिक क्षेत्रों / गुणों के साथ है, स्थैतिक तरीकों से नहीं।
असद सईदुद्दीन

10

यह दिलचस्प है पढ़ें:

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

ReSharper वास्तव में यह सुझाव नहीं दे रहा है कि आप अपनी विधि को स्थिर बनाएं। आपको अपने आप से पूछना चाहिए कि यह विधि उस वर्ग में क्यों है, जैसा कि कहना है, एक वर्ग जो अपने हस्ताक्षर में दिखाता है ...

लेकिन यहाँ क्या resharper documentaion कहते हैं: http://confluence.jetbrains.net/display/ReSharper/Member+can+be+made+static


2
मुझे लगता है कि यह बिंदु कमतर है। क्या उपकरण वास्तव में आपको बता रहा है कि विधि केवल कुछ अन्य वर्ग के सदस्यों पर संचालित होती है। यदि यह किसी प्रकार का कमांड (या "केस का उपयोग करें" या "इंटरेक्टर") ऑब्जेक्ट है, तो अन्य वस्तुओं में हेरफेर करने की जिम्मेदारी किसकी है, यह ठीक है। हालाँकि, अगर यह केवल एक अन्य वर्ग को हेरफेर करता है जो कि फीचर ईर्ष्या जैसा लगता है ।
ग्रेग

9

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


6

आपको ऐसा करना चाहिए जो दिए गए परिदृश्य में सबसे अधिक पठनीय और सहज हो।

प्रदर्शन की दलील सबसे चरम स्थितियों को छोड़कर एक अच्छी बात नहीं है क्योंकि केवल एक चीज जो वास्तव में हो रही है वह यह है कि एक अतिरिक्त पैरामीटर ( this) उदाहरण के तरीकों के लिए स्टैक पर धकेल दिया जा रहा है।


6

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

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


5

ReSharper तर्क की जांच नहीं करता है। यह केवल जाँचता है कि विधि उदाहरण के सदस्यों का उपयोग करती है या नहीं। यदि विधि निजी है और केवल (शायद सिर्फ एक) उदाहरण विधियों द्वारा कहा जाता है, तो यह एक संकेत विधि है।


3

यदि फ़ंक्शन कई पृष्ठों में साझा किए जाते हैं, तो आप उन्हें एक बेस पेज क्लास में भी डाल सकते हैं, और फिर सभी asp.net पृष्ठ हैं जो उस कार्यक्षमता से प्राप्त करते हैं (और फ़ंक्शन अभी भी स्थिर हो सकते हैं)।


3

एक विधि को स्थिर बनाने का मतलब है कि आप उस वर्ग का उदाहरण बनाए बिना कक्षा के बाहर से विधि को कॉल कर सकते हैं। तृतीय-पक्ष विक्रेता ऑब्जेक्ट या ऐड-ऑन के साथ काम करते समय यह मददगार होता है। कल्पना करें कि क्या आपको कॉल करने से पहले पहले एक कंसोल ऑब्जेक्ट "con" बनाना था। writeline ();


Java आपको con.Writeline () को कॉल करने से पहले कंसोल ऑब्जेक्ट बनाने के लिए फ़ैक्टरी इंस्टेंस बनाकर देता होगा।
स्कॉटमीचौड

2

यह नाम स्थान के प्रदूषण को नियंत्रित करने में मदद करता है।


8
कैसे एक विधि स्थिर बनाने से नाम स्थान प्रदूषण से बचने में मदद मिलती है?
लॉकस्टॉक

1
अनुभव से, स्टैटिक विधियों के साथ कक्षाओं में समूहों को जोड़कर, आप उन सभी कार्यों के "ग्रैब बैग" के उपसर्ग करने के अनुभव से बच रहे हैं जो अन्य पुस्तकालय या अंतर्निहित कार्यों के साथ संघर्ष कर सकते हैं। स्थिर विधियों के साथ, वे प्रभावी रूप से Classname, ex के तहत नामांकित हैं। Class.a_core_function( .. )बनामa_core_function( .. )
लिंटुक्सवी

0

बस मेरा tuppence: एक उपयोगिता वर्ग के लिए सभी साझा स्थिर तरीकों को जोड़ना आपको जोड़ने की अनुमति देता है

using static className; 

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

मुझे नहीं पता कि यह अच्छा अभ्यास है या नहीं। मेरे पास C # 4/5 के बारे में जानने के लिए बहुत कुछ है और रिफ्लेक्टर के लिए इतना विरासत कोड है कि मैं सिर्फ Roselyn टिप्स को गाइड करने की कोशिश कर रहा हूं।

एक छोटा सा सिक्का


0

मुझे उम्मीद है, आप पहले से ही स्थैतिक और उदाहरण के तरीकों के बीच अंतर को समझ चुके होंगे। साथ ही, एक लंबा उत्तर और एक छोटा उत्तर हो सकता है। लंबे उत्तर पहले से ही दूसरों द्वारा प्रदान किए जाते हैं।

मेरा संक्षिप्त जवाब: हां, यदि आप Resharper सुझाव देते हैं , तो आप उन्हें स्थिर तरीकों में बदल सकते हैं। ऐसा करने में कोई बुराई नहीं है। बल्कि, विधि को स्थिर बनाकर, आप वास्तव में विधि की रखवाली कर रहे हैं ताकि, अनावश्यक रूप से आप उस विधि के लिए किसी भी उदाहरण के सदस्यों को पर्ची न करें। इस तरह, आप एक ओओपी सिद्धांत प्राप्त कर सकते हैं " कक्षाओं और सदस्यों की पहुंच को कम करें "।

जब ReSharper यह सुझाव दे रहा है कि एक इंस्टेंस मेथड को स्टैटिक मेथड में बदला जा सकता है, तो यह वास्तव में आपको बता रहा है, "क्यों .. यह विधि इस वर्ग में बैठी है क्योंकि यह वास्तव में इसके किसी भी राज्य का उपयोग नहीं कर रही है?" तो, यह आपको विचार के लिए भोजन देता है। फिर, यह वह है जो उस पद्धति को स्थिर उपयोगिता वर्ग में ले जाने की आवश्यकता का एहसास कर सकता है या नहीं। SOLID सिद्धांतों के अनुसार, एक वर्ग के पास केवल एक मुख्य जिम्मेदारी होनी चाहिए। तो, आप उस तरीके से अपनी कक्षाओं की बेहतर सफाई कर सकते हैं। कभी-कभी, आपको अपने उदाहरण वर्ग में भी कुछ सहायक विधियों की आवश्यकता होती है। यदि ऐसा है, तो आप उन्हें # भाग सहायक के भीतर रख सकते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.