छुपाने के संबंध में सी # में "नए" संशोधक के कुछ व्यावहारिक उपयोग क्या हैं?


21

सह-कार्यकर्ता और मैं newC # में कीवर्ड के व्यवहार को देख रहे थे क्योंकि यह छिपने की अवधारणा पर लागू होता है। से प्रलेखन :

एक आधार वर्ग से विरासत में प्राप्त सदस्य को स्पष्ट रूप से छिपाने के लिए नए संशोधक का उपयोग करें। विरासत में दिए गए सदस्य को छिपाने के लिए, उसे उसी नाम का उपयोग करके व्युत्पन्न वर्ग में घोषित करें, और नए संशोधक के साथ संशोधित करें।

हमने प्रलेखन पढ़ा है, और हम समझते हैं कि यह मूल रूप से क्या करता है और यह कैसे करता है। क्या हम वास्तव में एक संभाल नहीं मिल सकता है क्यों आप इसे पहली जगह में करने की आवश्यकता होगी। संशोधक 2003 के बाद से है, और हम दोनों के साथ काम कर रहे हैं .नेट इससे अधिक समय तक है और यह कभी नहीं आया है।

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

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


9
हो सकता है कि आपने इसे भी पढ़ा हो, लेकिन एरिक लिपर्ट (सी # कंपाइलर डेवलपर) का एक दिलचस्प लेख है कि क्यों विधि छिपाई को C #: blogs.msdn.com/b/ericlippert/archive/2008/05/21// पर जोड़ा गया। । यह आपके प्रश्न का उत्तर देता है, लेकिन मेरे पास आपके लिए कोई व्यावसायिक मामला तैयार नहीं है इसलिए मैंने इसे एक टिप्पणी में रखा।
जालौन

3
@ जालयन: व्यवसायिक मामले की चर्चा एरिक ने इस पोस्ट में की है: blogs.msdn.com/b/ericlippert/archive/2004/01/07/…
ब्रायन

जवाबों:


22

आप इसका उपयोग रिटर्न प्रकार सहसंयोजक की नकल करने के लिए कर सकते हैं। एरिक लिपर्ट का स्पष्टीकरण । एरिक यह उदाहरण कोड प्रदान करता है:

abstract class Enclosure
{
    protected abstract Animal GetContents();
    public Animal Contents() { return this.GetContents(); }
}
class Aquarium : Enclosure
{
    public new Fish Contents() { ... }
    protected override Animal GetContents() { return this.Contents(); }
}

यह एक काम है। public override Fish Contents() { ... }सुरक्षित होने के बावजूद कानूनी नहीं है।

सामान्य तौर पर, आपको विधि छिपाने का उपयोग नहीं करना चाहिए , क्योंकि यह आपके वर्ग के उपभोक्ताओं को भ्रमित कर रहा है (ऊपर का विशिष्ट उदाहरण इस समस्या से ग्रस्त नहीं है)। यदि आप किसी मौजूदा विधि को ओवरराइड नहीं करना चाहते हैं, तो अपनी नई पद्धति को कुछ और नाम दें।

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

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

इस स्थिति पर इस पोस्ट में एरिक लिपर्ट द्वारा विस्तार से चर्चा की गई है ।


1
+1 newयह "भयानक और भ्रामक है" के लिए एक मार्कर होने के लिए।
अवनेर शाहर-कश्तन

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

4

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

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


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

3

यह पाठक को बता रहा है कि "मैंने जानबूझकर बेस क्लास 'इस पद्धति के कार्यान्वयन को छिपाया", गलती से विरोध किया।


5
यह मुझे भीख माँगते हुए सवाल करता है। ओपी जानता है कि वह क्या करता है लेकिन यह जानना चाहता है कि क्यों।
ब्रायन

0

आप पिछले सदस्य को अन्य नाम से उपलब्ध करवाना चाहते हैं:

class VehicleClass
{
  public int AnyProperty
  {
    get; set;
  }

  public int AnyFunction() { return 0; }
} // VehicleClass

class IntermediateClass : VehicleClass
{
  public int PreviousAnyProperty
  {
    get { return AnyProperty; }
    set { AnyProperty = value  }
  }

  public int PreviousAnyFunction() { return AnyFunction(); }
} // IntermediateClass 

class CarClass : IntermediateClass
{
  public new int AnyProperty
  {
    get ; set ;
  }

  public new int AnyFunction() { return 5; }
} // class CarClass

class ExampleClass
{

  public static void Main()
  {
    using (CarClass MyCar = new CarClass())
    {
      int AnyInt1 = MyCar.PreviousAnyProperty;
      MyCar.PreviousAnyProperty = 7;

      int AnyInt2 = MyCar.PreviousAnyFunction();

      int AnyInt3 = MyCar.AnyProperty;
      MyCar.AnyProperty = 45;

      int AnyInt4 = MyCar.AnyFunction();
    }
  } // static void Main()

} // class CarClass

चीयर्स।


मैं यह कैसे काम करता से परिचित हूँ, लेकिन मेरे सवाल का सही मायने में है क्यों आप पिछले सदस्य एक और नाम के माध्यम से उपलब्ध करना चाहते हैं? यह सभी प्रकार के अनुबंधों को तोड़ता है, कुछ सामान्य टुकड़ों को बेकार कर देता है।
जोएल एथर्टन

@ जॉयल एथरटन: जैसा कि आप जानते हैं कि यह कभी-कभी हो सकता है, कभी-कभी डेवलपर्स को अन्य लोगों को प्रोग्रामिंग कोड "पिक" करना पड़ता है। और हम संशोधित करने के लिए अधिकृत नहीं हो सकते हैं, शायद कक्षाओं का विस्तार करें। और दोनों पिछले सदस्य और नए का उपयोग करने की आवश्यकता हो सकती है।
umlcat

0

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

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