एक आंतरिक कक्षा में एक सार्वजनिक पद्धति का उपयोग क्यों करें?


250

हमारी एक परियोजना में बहुत सारे कोड हैं जो इस तरह दिखता है:

internal static class Extensions
{
    public static string AddFoo(this string s)
    {
        if (s == null)
        {
            return "Foo";
        }

        return $({s}Foo);
    }
}

क्या इसके अलावा ऐसा करने का कोई स्पष्ट कारण है "बाद में सार्वजनिक करना आसान है?"

मुझे संदेह है कि यह केवल बहुत ही अजीब धार मामलों (सिल्वरलाइट में प्रतिबिंब) या बिल्कुल भी नहीं होता है।


1
मेरे अनुभव में, यह सामान्य अभ्यास है।
फोग

2
@ फोग, ओके। लेकिन यह सामान्य अभ्यास क्यों है? शायद बस आसान तो आंतरिक करने के लिए तरीकों का एक गुच्छा बदल रहा है? त्वरित सुधार -> इसके बजाय आंतरिक प्रकार को चिह्नित करें?
bopapa_1979

यही मैंने हमेशा ग्रहण किया है। मेरे पास एक सुविचारित विश्लेषण नहीं है, हालांकि, यही कारण है कि मैंने उत्तर नहीं दिया।
फोज

2
एरिक लिपर्ट का जवाब मेरी सोच को बहुत अच्छी तरह से बताता है, और कुछ ऐसा भी लाता है जो मेरे दिमाग में एक तरह से पता लगाने की कोशिश कर रहा था: इंटरफ़ेस सदस्यों के निहित कार्यान्वयन सार्वजनिक होना चाहिए।
फोग

उस विधि के बराबर नहीं है return s + "Foo";? +ऑपरेटर शून्य या खाली स्ट्रिंग के बारे में परवाह नहीं है।
मिकेल आर। लंड

जवाबों:


419

अद्यतन: यह सवाल सितंबर 2014 में मेरे ब्लॉग का विषय था । महान प्रश्न के लिए धन्यवाद!

कंपाइलर टीम के भीतर भी इस सवाल पर काफी बहस हुई है।

सबसे पहले, नियमों को समझना बुद्धिमानी है। एक वर्ग या संरचना का एक सार्वजनिक सदस्य एक ऐसा सदस्य है जो किसी भी चीज के लिए सुलभ है जो युक्त प्रकार तक पहुंच सकता है । तो एक आंतरिक वर्ग का एक सार्वजनिक सदस्य प्रभावी रूप से आंतरिक है।

तो अब, एक आंतरिक वर्ग को देखते हुए, क्या इसके सदस्य जिन्हें आप विधानसभा में पहुंचना चाहते हैं, उन्हें सार्वजनिक या आंतरिक के रूप में चिह्नित किया जाना चाहिए?

मेरी राय है: ऐसे सदस्यों को सार्वजनिक रूप से चिह्नित करें।

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

मूल रूप से, मेरा दृष्टिकोण है: मान लीजिए कि मैंने इस आंतरिक वर्ग को एक सार्वजनिक वर्ग में बनाने का फैसला किया। ऐसा करने के लिए, मैं बिल्कुल एक चीज बदलना चाहता हूं : कक्षा की पहुंच। यदि एक आंतरिक वर्ग को सार्वजनिक वर्ग में बदलने का अर्थ है कि मुझे एक आंतरिक सदस्य को भी सार्वजनिक सदस्य में बदलना है, तो वह सदस्य वर्ग के सार्वजनिक सतह क्षेत्र का हिस्सा था , और इसे पहली जगह में सार्वजनिक होना चाहिए था।

अन्य लोग असहमत हैं। एक आकस्मिक बात है जो कहती है कि वे किसी सदस्य की घोषणा पर नज़र रखना चाहते हैं और तुरंत जानते हैं कि क्या यह केवल आंतरिक कोड से कहा जाने वाला है।

दुर्भाग्य से, यह हमेशा अच्छी तरह से काम नहीं करता है; उदाहरण के लिए, एक आंतरिक वर्ग जो एक आंतरिक इंटरफ़ेस को लागू करता है, को अभी भी कार्यान्वयन करने वाले सदस्यों को सार्वजनिक रूप से चिह्नित करना होगा, क्योंकि वे वर्ग की सार्वजनिक सतह का हिस्सा हैं


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

10
+1 यह कहने के लिए कि मैं क्या कहना चाहता था, लेकिन मैं जितना सक्षम था, उससे भी ज्यादा बेहतर तरीके से तैयार कर रहा था (इंटरफ़ेस कोण को ऊपर लाने के लिए, हालांकि मैं ध्यान देता हूं कि यह केवल निहित सदस्य कार्यान्वयन का सच है)।
फोज

2
इंटरफ़ेस भाग महत्वपूर्ण है - आंतरिक का उपयोग करके एक इंटरफ़ेस विधि को लागू करना असंभव है, यह या तो सार्वजनिक या स्पष्ट इंटरफ़ेस घोषणा है। इसलिए सार्वजनिक शब्द दो अर्थों से भरा हुआ है।
माइकल Stum

8
एक सैद्धांतिक दृष्टिकोण से आपके पक्ष में तर्क publicबहुत ही ठोस है। हालांकि, मुझे लगता है कि "हमेशा अच्छी तरह से काम नहीं करता है ..." विशेष रूप से शक्तिशाली होने के लिए। निरंतरता खो देने से किसी भी "पर-एक-नज़र" लाभ का अवमूल्यन होता है। internalइस तरह से उपयोग करने का अर्थ है जानबूझकर अंतर्ज्ञान का निर्माण करना जो कभी-कभी गलत होते हैं। ज्यादातर सही-सही अंतर्ज्ञान होना IMO प्रोग्रामिंग के लिए एक भयानक बात है।
ब्रायन

3
आपके ब्लॉग पोस्ट से महत्वपूर्ण उद्धरण: "मेरी सलाह है कि अपनी टीम के बीच इस मुद्दे पर चर्चा करें, निर्णय लें, और फिर उससे चिपके रहें।"
bopapa_1979

17

यदि क्लास है internal, तो यह एक्सेसिबिलिटी के दृष्टिकोण से कोई फर्क नहीं पड़ता है कि आप कोई विधि चिह्नित करते हैं internalया नहीं public। हालाँकि यह तब भी अच्छा है जब आप वर्ग का उपयोग करेंगे public

जबकि कुछ लोगों ने कहा है कि इससे संक्रमण में आसानी होती internalहै public। यह विधि के विवरण के भाग के रूप में भी कार्य करता है। Internalतरीकों को आमतौर पर अनफिट एक्सेस के लिए असुरक्षित माना जाता है, जबकि publicतरीकों को (ज्यादातर) फ्री गेम माना जाता है।

किसी कक्षा में आप का उपयोग करके internalया publicजैसा भी हो public, आप यह सुनिश्चित करते हैं कि आप संवाद कर रहे हैं कि publicभविष्य में कक्षा बनाने के लिए आवश्यक कार्य को आसान बनाने के साथ-साथ उपयोग की कौन सी शैली अपेक्षित है ।


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

@ एरिक: यदि आप किसी विधि की सुरक्षितता का निर्धारण तब तक करना चाहते हैं जब तक कि आप तैयार न हों, लेकिन मैं केवल सुरक्षित समझे जाने वाले तरीकों की बात कर रहा था, जिसमें कोई खुलासा नहीं है।
ग्वेंटे

10

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


जवाब के लिए धन्यवाद। मैं ज़िद करता हूँ कि कोडिंग करते समय "सब कुछ" मायने रखता है, हालाँकि :)
bopapa_1979

1
आप एरिक सही हैं, यह एक फेंक टिप्पणी का एक सा था। आशा है कि मेरे बाकी जवाब कुछ काम के थे। मुझे लगता है कि एरिक लिपर्ट का जवाब है जिसे मैं व्यक्त करने की कोशिश कर रहा था, लेकिन उन्होंने इसे इतना बेहतर बताया।
Ɖiamond ǤeezeƦ

8

मुझे संदेह है कि "बाद में प्रकार को सार्वजनिक करना आसान है?" क्या यह।

स्कूपिंग नियमों का मतलब है कि विधि केवल इस रूप में दिखाई देगी internal- इसलिए यह वास्तव में कोई फर्क नहीं पड़ता कि क्या तरीके चिह्नित हैं publicया internal

एक संभावना जो मन में आती है वह यह है कि वर्ग सार्वजनिक था और बाद में बदल दिया गया था internalऔर डेवलपर ने सभी विधि एक्सेसिबिलिटी संशोधक को बदलने की जहमत नहीं उठाई।


1
स्पष्ट "सार्वजनिक वर्ग आंतरिक हो गया" परिदृश्य के लिए +1।
bopapa_1979 22

8

कुछ मामलों में, यह भी हो सकता है कि आंतरिक प्रकार एक सार्वजनिक इंटरफ़ेस को लागू करता है, जिसका अर्थ होगा कि उस इंटरफ़ेस पर परिभाषित किसी भी तरीके को अभी भी सार्वजनिक घोषित करने की आवश्यकता होगी।


2

यह समान है, सार्वजनिक विधि वास्तव में आंतरिक के रूप में चिह्नित की जाएगी क्योंकि यह एक आंतरिक वर्ग के अंदर है, लेकिन इसमें एक आजीवन (जैसा कि आपने मेहमान रखा है), यदि आप वर्ग को सार्वजनिक रूप से चिह्नित करना चाहते हैं, तो आपको कम कोड बदलना होगा।


2
वहाँ पहले से ही एक संबंधित प्रश्न है: stackoverflow.com/questions/711361/…
मारियो कॉरेरो

0

internalकहते हैं कि सदस्य को केवल उसी विधानसभा के भीतर से पहुँचा जा सकता है। उस विधानसभा में अन्य वर्ग internal publicसदस्य तक पहुँच सकते हैं , लेकिन किसी सदस्य privateया protectedसदस्य तक नहीं पहुँच पाएंगे internal


लेकिन अगर तरीकों को चिह्नित internalकिया गया public, तो उनकी दृश्यता नहीं बदलेगी। मेरा मानना ​​है कि ओपी किस बारे में पूछ रहा है।
ओड

1
@zapthedingbat - पोस्ट तथ्यात्मक रूप से सही है, लेकिन क्या यह वास्तव में सवाल का जवाब दे रहा है?
ओड

1
ठीक है, सवाल यह है कि क्यों उन्हें इस तरह से चिह्नित किया जाता है। मैं दायरे की मूल बातें समझता हूं। इस प्रयास के लिए धन्यवाद, हालांकि!
bopapa_1979

0

मैं वास्तव में आज इससे जूझ रहा हूं। अब तक मैंने कहा होगा कि internalयदि सभी वर्ग के साथ तरीकों को चिह्नित किया जाना चाहिए internalऔर विशेष रूप से उद्यम विकास में केवल खराब कोडिंग या आलस्य के अलावा कुछ और माना जाता है; हालाँकि, मुझे एक publicवर्ग को उप-वर्ग करना पड़ा और इसकी एक विधि को ओवरराइड करना पड़ा :

internal class SslStreamEx : System.Net.Security.SslStream
{
    public override void Close()
    {
        try
        {
            // Send close_notify manually
        }
        finally
        {
            base.Close();
        }
    }
}

विधि होना जरूरी है publicऔर मुझे यह सोचकर मिला है कि विधियों को स्थापित करने के लिए वास्तव में कोई तार्किक बिंदु नहीं है internalजब तक कि उन्हें वास्तव में होना चाहिए, जैसा कि एरिक लिपर्ट ने कहा।

अब तक मैं वास्तव में इसके बारे में सोचने के लिए कभी नहीं रुका, मैंने अभी इसे स्वीकार कर लिया है, लेकिन एरिक के पोस्ट को पढ़ने के बाद यह वास्तव में मुझे सोच में पड़ गया और बहुत विचार-विमर्श के बाद यह बहुत मायने रखता है।


0

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


0

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

ऐशे ही:

public sealed class MyCurrentlySealedClass
{
    protected void MyCurretlyPrivateMethod()
    {
    }
}

"पैटर्न" के अनुसार मैंने ऊपर उल्लेख किया है, यह पूरी तरह से ठीक होना चाहिए। यह उसी विचार का अनुसरण करता है। यह एक privateविधि के रूप में व्यवहार करता है , क्योंकि आप कक्षा को विरासत में नहीं ले सकते। लेकिन अगर आप sealedबाधा को हटाते हैं , तो यह अभी भी मान्य है: विरासत में मिली कक्षाएं इस पद्धति को देख सकती हैं, जो कि बिल्कुल वही है जो मैं हासिल करना चाहती थी। लेकिन आपको एक चेतावनी मिलती है: CS0628या CA1047। वे दोनों protectedएक sealedवर्ग में सदस्यों की घोषणा नहीं करते हैं । इसके अलावा, मुझे पूर्ण सहमति मिली है, इस बारे में यह समझ में नहीं आता है: 'सीलबंद वर्ग में संरक्षित सदस्य' चेतावनी (एक एकल वर्ग)

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


मैं इसे (या कम से कम कारणों से) करना पसंद करता हूं, एरिक लिपर्ट ने कहा। उनका लेख निश्चित रूप से पढ़ने लायक है।
bopapa_1979
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.