C # इंटरफ़ेस को लागू करने के लिए स्टेटिक तरीकों की अनुमति क्यों नहीं देता?


447

C # को इस तरह से क्यों बनाया गया?

जैसा कि मैं इसे समझता हूं, एक इंटरफ़ेस केवल व्यवहार का वर्णन करता है, और कुछ व्यवहार को लागू करने वाले इंटरफ़ेस को लागू करने वाली कक्षाओं के लिए एक संविदात्मक दायित्व का वर्णन करने के उद्देश्य से कार्य करता है।

यदि कक्षाएं साझा पद्धति में उस व्यवहार को लागू करना चाहती हैं, तो उन्हें क्यों नहीं करना चाहिए?

यहाँ एक उदाहरण है जो मेरे मन में है:

// These items will be displayed in a list on the screen.
public interface IListItem {
  string ScreenName();
  ...
}

public class Animal: IListItem {
    // All animals will be called "Animal".
    public static string ScreenName() {
        return "Animal";
    }
....
}

public class Person: IListItem {

    private string name;

    // All persons will be called by their individual names.
    public string ScreenName() {
        return name;
    }

    ....

 }

6
खैर, जावा 8 में यह ( stackoverflow.com/questions/23148471/… ) है।
लियांग

1
देखें कि आप विरासत या इंटरफ़ेस के कार्यान्वयन के साथ एक स्थिर व्यवहार को कैसे जोड़ सकते हैं: stackoverflow.com/a/13567309/880990
ओलिवियर जैकोट-डेसकोम्बे जूल 30'16

1
IListItem.ScreenName() => ScreenName()(C # 7 सिंटैक्स का उपयोग करके) स्टैटिक विधि को कॉल करके इंटरफ़ेस विधि को स्पष्ट रूप से लागू करेगा। जब आप उस से विरासत जोड़ते हैं तो चीजें बदसूरत हो जाती हैं, हालाँकि (आपको इंटरफ़ेस को फिर से लागू करना होगा)
जीरो मोस्टर्ट

2
बस सभी को पता है कि अब इंतजार खत्म हो गया है! C # 8.0 में स्टैटिक इंटरफ़ेस विधियाँ हैं: dotnetfiddle.net/Lrzy6y (हालाँकि वे काम करने के लिए ओपी के काम करने के तरीके के बारे में थोड़ा अलग हैं - आपको उन्हें लागू करने की ज़रूरत नहीं है)
जेमी ट्वेल्स

जवाबों:


221

यह मानते हुए कि आप ऐसा क्यों कर रहे हैं:

public interface IFoo {
    void Bar();
}

public class Foo: IFoo {
    public static void Bar() {}
}

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


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

public class Animal: IListItem {
    /* Can be tough to come up with a different, yet meaningful name!
     * A different casing convention, like Java has, would help here.
     */
    public const string AnimalScreenName = "Animal";
    public string ScreenName(){ return AnimalScreenName; }
}

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


6
एक आदर्श उदाहरण! लेकिन मुझे यकीन नहीं है कि मैं आपका तर्क समझता हूँ। निश्चित रूप से संकलक के रूप में अच्छी तरह से स्टेटिक सदस्यों को देखने के लिए डिज़ाइन किया जा सकता था? क्या उदाहरणों में थिस विधियों के कार्यान्वयन के लिए पतों की एक तालिका नहीं है? क्या इस तालिका में स्थिर विधियों को शामिल नहीं किया जा सकता है?
क्रामि

12
एक ऐसा मामला है जहां यह उपयोगी हो सकता है। उदाहरण के लिए, मैं चाहता हूं कि सभी कार्यान्वयनकर्ता GetInstance पद्धति को लागू करें जो एक XElement तर्क लेता है। मैं न तो इंटरफ़ेस में एक स्थिर विधि के रूप में परिभाषित कर सकता हूं, और न ही इंटरफ़ेस से एक निर्माता के हस्ताक्षर की मांग कर सकता हूं।
oleks

25
बहुत सारे लोगों ने दोनों पक्षों पर तौला है: "इससे कोई मतलब नहीं है" से "यह एक बग है, काश आप कर सकते।" (मुझे लगता है कि इसके लिए वैध उपयोग के मामले हैं, जो है कि मैं यहाँ कैसे समाप्त हुआ।) वर्कअराउंड के रूप में, उदाहरण विधि बस एक स्थिर विधि को सौंप सकती है।
हर्पो

5
आप बस आधार इंटरफ़ेस पर एक विस्तार विधि के रूप में इस टुकड़े को लागू कर सकते हैं, जैसे कि: public static object MethodName(this IBaseClass base)एक स्थिर वर्ग के भीतर। हालांकि, नकारात्मक पक्ष यह है कि एक इंटरफ़ेस वंशानुक्रम के विपरीत - यह व्यक्तिगत उत्तराधिकारियों को कार्यप्रणाली को अच्छी तरह से ओवरराइड करने की अनुमति नहीं देता है।
ट्रॉय अल्फोर्ड

8
यह जेनेरिक के साथ बहुत मायने रखेगा। उदाहरण के लिए शून्य कुछ <T> () जहां T: ISomeInterface {new T ()। DoSomething1 (); T.DoSomething2 (); }
फ्रांसिस्को रेयान टोल्मास्की I 10

173

मेरा (सरलीकृत) तकनीकी कारण यह है कि स्थिर विधियाँ व्यवहार्य नहीं हैं , और संकलन समय पर कॉल साइट को चुना जाता है। यही कारण है कि आपके पास ओवरराइड या वर्चुअल स्टैटिक सदस्य नहीं हो सकते हैं। अधिक जानकारी के लिए, आपको CS ग्रेड या कंपाइलर विंडक की आवश्यकता होगी - जिसमें से मैं न तो हूं।

राजनीतिक कारण के लिए, मैं एरिक लिपर्ट (जो कि एक संकलित चरखी है, और वाटरलू विश्वविद्यालय से गणित, कंप्यूटर विज्ञान और एप्लाइड गणित में स्नातक की उपाधि प्राप्त करूँगा) को उद्धृत करूँगा (स्रोत: लिंक्डइन ):

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

ध्यान दें कि लिप्टर्ट तथाकथित प्रकार की विधि के लिए जगह छोड़ता है:

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

लेकिन अभी तक इसकी उपयोगिता के बारे में आश्वस्त नहीं है।


5
बहुत बढ़िया, यह वह उत्तर है जो मैं लिखना चाहता था - मुझे कार्यान्वयन का विवरण नहीं पता था।
क्रिस मरास्टी-जार्ज

5
बहुत बढ़िया जवाब। और मुझे यह 'टाइप मेथड' चाहिए! इतने अवसरों में उपयोगी होगा (एक प्रकार / वर्ग के लिए मेटाडेटा के बारे में सोचें)।
फिलिप डबमीयर

23
यह सही जवाब है। आप किसी को एक इंटरफ़ेस पास करते हैं, उन्हें यह जानने की जरूरत है कि किसी विधि को कैसे कॉल किया जाए। एक इंटरफ़ेस सिर्फ एक वर्चुअल मेथड टेबल है । आपके स्थिर वर्ग के पास ऐसा नहीं है। फोन करने वाले को पता नहीं होगा कि कैसे एक विधि को कॉल किया जाए। (इससे पहले कि मैं इस जवाब को पढ़ता हूं मुझे लगा कि C # सिर्फ पांडित्यपूर्ण हो रहा है। अब मुझे एहसास हुआ कि यह एक तकनीकी सीमा है, जो एक इंटरफेस द्वारा लगाया गया है ।) अन्य लोग आपसे बात करेंगे कि यह एक खराब डिजाइन कैसे है। यह एक बुरा डिज़ाइन नहीं है - यह एक तकनीकी सीमा है।
इयान बॉयड

2
+1 वास्तव में सवाल का जवाब देने और पांडित्य और स्नॉट्टी नहीं होने के लिए। जैसे इयान बॉयड ने कहा: "यह एक बुरा डिज़ाइन नहीं है - यह एक तकनीकी सीमा है।"
जोशुआ पेच

3
यह एक पूरी तरह से सम्बद्ध स्थिर के साथ एक स्थिर वर्ग के लिए एक वस्तु उत्पन्न करने के लिए संभव है। देखिए कि स्केला कैसे संभालती है objectऔर उन्हें इंटरफेस लागू करने की अनुमति कैसे दी जाती है।
सेबेस्टियन ग्राफ

97

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

मान लीजिए कि हमारे पास जेनेरिक पद्धति में टाइप पैरामीटर है और हमें इसके साथ कुछ ऑपरेशन करने की आवश्यकता है। हम तात्कालिकता नहीं चाहते, क्योंकि हम निर्माणकर्ताओं से अनजान हैं।

उदाहरण के लिए:

Repository GetRepository<T>()
{
  //need to call T.IsQueryable, but can't!!!
  //need to call T.RowCount
  //need to call T.DoSomeStaticMath(int param)
}

...
var r = GetRepository<Customer>()

दुर्भाग्य से, मैं केवल "बदसूरत" विकल्प के साथ आ सकता हूं:

  • प्रतिबिंब बदसूरत का प्रयोग करें और इंटरफेस और बहुरूपता के विचार को धड़कता है।

  • पूरी तरह से अलग कारखाना वर्ग बनाएँ

    इससे कोड की जटिलता बहुत बढ़ सकती है। उदाहरण के लिए, यदि हम डोमेन ऑब्जेक्ट्स को मॉडल करने की कोशिश कर रहे हैं, तो प्रत्येक ऑब्जेक्ट को दूसरे रिपॉजिटरी क्लास की आवश्यकता होगी।

  • त्वरित और फिर इच्छित इंटरफ़ेस विधि को कॉल करें

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

उदाहरण:

public class Customer 
{
  //create new customer
  public Customer(Transaction t) { ... }

  //open existing customer
  public Customer(Transaction t, int id) { ... }

  void SomeOtherMethod() 
  { 
    //do work...
  }
}

स्थिर इंटरफ़ेस समस्या को हल करने के लिए तात्कालिकता का उपयोग करने के लिए हमें निम्नलिखित कार्य करने की आवश्यकता है:

public class Customer: IDoSomeStaticMath
{
  //create new customer
  public Customer(Transaction t) { ... }

  //open existing customer
  public Customer(Transaction t, int id) { ... }

  //dummy instance
  public Customer() { IsDummy = true; }

  int DoSomeStaticMath(int a) { }

  void SomeOtherMethod() 
  { 
    if(!IsDummy) 
    {
      //do work...
    }
  }
}

यह स्पष्ट रूप से बदसूरत है और अनावश्यक भी अन्य सभी तरीकों के लिए कोड को जटिल करता है। जाहिर है, एक सुरुचिपूर्ण समाधान भी नहीं!


35
+1 के लिए "अधिकांश उत्तर यहां पूरे बिंदु को याद करते हैं।" यह अविश्वसनीय है कि यह कैसे लगता है कि बहुत सारे जवाब सवाल का मूल चकमा दे देते हैं ज्यादातर

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

6
@ क्रिस मैं असहमत हूँ, बड़े पैमाने पर ओवरकिल। यह हमेशा एक भाषा दोष का संकेत है जब अधिक वास्तुकला 'सबसे अच्छा' समाधान है। याद रखें कि सभी पैटर्न सी # के बारे में कोई भी बात नहीं करता है क्योंकि सी # में जेनरिक और अनाम तरीके हैं?
मैटमैनसर

3
क्या आप "जहां T: IQueryable, T: IDoSomeStaticMath" या समान का उपयोग नहीं कर सकते हैं?
रोजर विल्कॉक्स

2
@ क्रिसमार्स्टी-जॉर्ज: इसके आस-पास कुछ गंदा लेकिन दिलचस्प तरीका यह थोड़ा सा निर्माण है: public abstract class DBObject<T> where T : DBObject<T>, new()और फिर सभी डीबी वर्गों को विरासत में मिला DBObject<T>। फिर आप पुनः प्राप्त कर सकते हैं-कुंजी को स्थिर सुपरक्लास में वापसी प्रकार T के साथ एक स्थिर फ़ंक्शन बनाते हैं, उस फ़ंक्शन को T की एक नई वस्तु बनाते हैं, और फिर String GetRetrieveByKeyQuery()उस ऑब्जेक्ट पर एक संरक्षित (सुपरक्लास पर सार के रूप में परिभाषित) कॉल करने के लिए प्राप्त करते हैं निष्पादित करने के लिए वास्तविक क्वेरी। यद्यपि यह विषय से
छेड़छाड़

20

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

स्ट्रिंग DoSomething <T> () जहां T: ISomeFunction
{
  यदि (T.someFunction)
    ...
}

स्थैतिक तरीके से सक्षम होने के कारण एक इंटरफ़ेस लागू होता है जो आप चाहते हैं वह प्राप्त नहीं होगा; क्या जरूरत होगी एक इंटरफ़ेस के हिस्से के रूप में स्थिर सदस्यों के लिए । मैं निश्चित रूप से इसके लिए कई उपयोग मामलों की कल्पना कर सकता हूं, खासकर जब बात चीजों को बनाने में सक्षम होने की आती है। दो दृष्टिकोण जो मैं मददगार हो सकते हैं:

  1. एक स्टैटिक जेनेरिक क्लास बनाएं जिसका टाइप पैरामीटर वह प्रकार होगा जो आप ऊपर दिए गए DoSomething को पास करेंगे। इस वर्ग की प्रत्येक भिन्नता में उस प्रकार से संबंधित सामान रखने वाले एक या अधिक स्थिर सदस्य होंगे। इस जानकारी की आपूर्ति या तो प्रत्येक वर्ग को "रजिस्टर जानकारी" रूटीन कॉल करने से हो सकती है, या वर्ग भिन्नता के स्थिर निर्माणकर्ता के चलने पर सूचना प्राप्त करने के लिए परावर्तन का उपयोग करके। मेरा मानना ​​है कि बाद वाले दृष्टिकोण की तुलना कंप्रैसर <टी> .डॉफॉल्ट () जैसी चीजों द्वारा की जाती है।
  2. ब्याज के प्रत्येक वर्ग टी के लिए, एक वर्ग या संरचना को परिभाषित करें जो IGetWhateverClassInfo <T> को लागू करता है और एक "नया" बाधा को संतुष्ट करता है। वर्ग में वास्तव में कोई फ़ील्ड नहीं होगी, लेकिन एक स्थिर संपत्ति होगी जो टाइप जानकारी के साथ एक स्थिर फ़ील्ड लौटाती है। सामान्य प्रश्न में उस वर्ग या संरचना के प्रकार को पास करें, जो एक उदाहरण बनाने में सक्षम होगा और दूसरे वर्ग के बारे में जानकारी प्राप्त करने के लिए इसका उपयोग करेगा। यदि आप इस उद्देश्य के लिए एक वर्ग का उपयोग करते हैं, तो आपको हर बार एक नए जेनेरेटर-ऑब्जेक्ट उदाहरण के निर्माण से बचने के लिए, जैसा कि ऊपर बताया गया है, एक स्थिर जेनेरिक क्लास को परिभाषित करना चाहिए। यदि आप एक संरचना का उपयोग करते हैं, तो इंस्टेंटिएशन लागत शून्य होनी चाहिए, लेकिन प्रत्येक अलग-अलग प्रकार के प्रकार के लिए DoSomething दिनचर्या के एक अलग विस्तार की आवश्यकता होगी।

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


16

लघु-दृष्टि, मुझे लगता है।

जब मूल रूप से डिजाइन किया गया था, तो इंटरफेस केवल कक्षा के उदाहरणों के साथ उपयोग करने के लिए थे

IMyInterface val = GetObjectImplementingIMyInterface();
val.SomeThingDefinedinInterface();

यह केवल इंटरफेस की शुरूआत के साथ था क्योंकि जेनेरिक के लिए बाधाओं ने एक इंटरफ़ेस के लिए एक स्थैतिक विधि को जोड़ना एक व्यावहारिक उपयोग किया है।

(टिप्पणी का जवाब देते हुए :) मेरा मानना ​​है कि इसे बदलने से अब सीएलआर में बदलाव की आवश्यकता होगी, जिससे मौजूदा असेंबली के साथ असंगतता हो सकती है।


यह जेनेरिक के संदर्भ में है कि मैंने पहली बार समस्या का सामना किया, लेकिन मुझे आश्चर्य है कि अगर इंटरफेस में स्थैतिक तरीके अन्य संदर्भों में भी उपयोगी हो सकते हैं? क्या कोई कारण है कि चीजों को बदला नहीं जा सकता है?
क्रामि

एक सामान्य वर्ग को लागू करते समय मुझे भी इसका सामना करना पड़ता है जिसमें कुछ मापदंडों के साथ खुद को बनाने के लिए पैरामीटर प्रकार की आवश्यकता होती है। चूंकि नया () कोई भी नहीं ले सकता है। क्या आपने यह पता लगाया कि यह कैसे करना है, क्रामि?
टॉम

1
@Kramii: स्थिर एपीआई के लिए अनुबंध। मुझे एक वस्तु उदाहरण नहीं चाहिए, बस एक विशेष हस्ताक्षर की गारंटी है, उदाहरण के लिए। IMatrixMultiplier या ICustomSerializer। कक्षा सदस्य के रूप में फंक / कार्य / प्रतिनिधि चाल करते हैं, लेकिन IMO कभी-कभी ओवरकिल की तरह लगता है, और एपीआई का विस्तार करने की कोशिश करने वाले अनुभवहीन के लिए भ्रमित हो सकता है।
डेविड क्यूकेया

14

वस्तु वस्तु का व्यवहार निर्दिष्ट करती है।

स्थैतिक विधियां किसी वस्तु के व्यवहार को निर्दिष्ट नहीं करती हैं, लेकिन व्यवहार जो किसी वस्तु को प्रभावित करता है।


71
क्षमा करें .. मुझे यकीन नहीं है कि यह सही है! एक इंटरफ़ेस व्यवहार को निर्दिष्ट नहीं करता है। एक इंटरफ़ेस नामित संचालन के एक सेट को परिभाषित करता है। दो कक्षाएं एक इंटरफ़ेस की विधि को पूरी तरह से अलग तरीके से व्यवहार करने के लिए लागू कर सकती हैं। इसलिए, एक इंटरफ़ेस व्यवहार को बिल्कुल भी निर्दिष्ट नहीं करता है। वह वर्ग जो इसे लागू करता है।
स्कॉट लैंगहम

1
आशा है कि आपको नहीं लगता कि मैं पिकी जा रहा हूँ .. लेकिन मुझे लगता है कि किसी भी ओओ को समझने के लिए यह एक महत्वपूर्ण अंतर है।
स्कॉट लैंगहम

4
एक इंटरफ़ेस एक अनुबंध को निर्दिष्ट करने वाला है जिसमें व्यवहार और प्रस्तुति शामिल है। यही कारण है कि एक इंटरफ़ेस कॉल के व्यवहार को बदलना एक नहीं-नहीं है क्योंकि दोनों को तय किया जाना चाहिए। यदि आपके पास एक इंटरफ़ेस है जहां कॉल अलग तरह से कार्य करता है (यानी IList.Add ने एक निष्कासन किया) तो यह सही नहीं होगा।
जेफ येट्स ने

14
ठीक है, हाँ, आप सिर में उसके नाम के साथ अनुचित व्यवहार करने की विधि को परिभाषित करेंगे। यदि आपके पास IAlertService.GetAssistance () है, तो यह व्यवहार एक प्रकाश फ्लैश, एक अलार्म ध्वनि, या एक छड़ी के साथ आंख में प्रहार हो सकता है।
स्कॉट लैंगहम

1
एक कार्यान्वयन लॉग फ़ाइल में लिखने में भी सक्षम होगा। यह व्यवहार इंटरफ़ेस में निर्दिष्ट नहीं है। लेकिन, शायद आप सही कह रहे हैं। 'सहायता प्राप्त करने' के व्यवहार का वास्तव में सम्मान किया जाना चाहिए।
स्कॉट लैंगहम

14

जिस हद तक इंटरफेस "अनुबंध" का प्रतिनिधित्व करता है, यह स्थिर वर्गों के लिए इंटरफेस को लागू करने के लिए उचित उचित लगता है।

उपरोक्त तर्क सभी अनुबंधों के बारे में इस बिंदु को याद करते हैं।


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

@SimonMourier यह प्रलेखन अधिक स्पष्ट रूप से लिखा जा सकता था, लेकिन आप इसे गलत बता रहे हैं। यह ICustomMarshaler इंटरफ़ेस नहीं है जिसे GetInstance स्थिर विधि की आवश्यकता है। यह [मार्शल] कोड विशेषता है जिसके लिए यह आवश्यक है। वे फैक्ट्री पैटर्न का उपयोग कर रहे हैं ताकि विशेषता को संलग्न मार्शलर का एक उदाहरण मिल सके। दुर्भाग्य से वे मार्शलों के प्रलेखन पृष्ठ पर GetInstance की आवश्यकता के दस्तावेज को शामिल करना पूरी तरह से भूल गए (यह केवल अंतर्निहित मार्शलों के कार्यान्वयन का उपयोग करके उदाहरण दिखाता है)।
स्कॉट गार्टनर

@ScottGartner - अपनी बात न समझें। msdn.microsoft.com/en-us/library/… स्पष्ट रूप से बताता है: "ICustomMarshaler इंटरफ़ेस को लागू करने के अलावा, कस्टम मार्शलों को GetInstance नामक एक स्टैटिक विधि को लागू करना चाहिए जो स्ट्रिंग को एक पैरामीटर के रूप में स्वीकार करता है और उसके पास एक प्रकार का ICustomMarshaler होता है।" स्थिर भाषा को सामान्य भाषा रनटाइम की COM इंटरोप लेयर द्वारा कस्टम मार्शलेयर के इंस्टेंस को इंस्टेंट करने के लिए कहा जाता है। " यह निश्चित रूप से एक स्थिर अनुबंध परिभाषा है।
सिमोन मूरियर

9

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

आप इसे कैसे कहेंगे ??


public interface MyInterface { void MyMethod(); }
public class MyClass: MyInterface
{
    public static void MyMethod() { //Do Something; }
}

 // inside of some other class ...  
 // How would you call the method on the interface ???
    MyClass.MyMethod();  // this calls the method normally 
                         // not through the interface...

    // This next fails you can't cast a classname to a different type... 
    // Only instances can be Cast to a different type...
    MyInterface myItf = MyClass as MyInterface;  

1
अन्य भाषाएं (उदाहरण के लिए जावा) स्थिर तरीकों को ऑब्जेक्ट इंस्टेंसेस से कॉल करने की अनुमति देती हैं, हालांकि आपको एक चेतावनी मिलेगी कि आपको उन्हें स्थिर संदर्भ से कॉल करना चाहिए।
क्रिस मरास्टी-जॉर्ज

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

1
@CharlesBretana जेनेरिक के मामले में, प्रकार में से एक के लिए पारित कर दिया। मैं स्थैतिक तरीकों के लिए इंटरफेस होने में बहुत उपयोगिता देखता हूं (या यदि आप चाहते हैं, तो हम उन्हें "स्थिर इंटरफेस" कहते हैं और एक वर्ग को अपने स्थिर इंटरफेस को परिभाषित करने की अनुमति देते हैं। और उदाहरण इंटरफेस)। इसलिए यदि मेरे पास है तो Whatever<T>() where T:IMyStaticInterfaceमैं कॉल कर सकता हूं Whatever<MyClass>()और बिना किसी उदाहरण की आवश्यकता T.MyStaticMethod()के Whatever<T>()कार्यान्वयन के अंदर हो सकता है । कॉल करने की विधि रनटाइम में निर्धारित की जाएगी। आप इसे प्रतिबिंब के माध्यम से कर सकते हैं, लेकिन मजबूर होने के लिए कोई "अनुबंध" नहीं है।
Jcl

4

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

T SumElements<T>(T initVal, T[] values)
{
    foreach (var v in values)
    {
        initVal += v;
    }
}

यहां कोई बहुरूपता नहीं है, जेनेरिक वास्तविक प्रकार की वस्तु का उपयोग करता है और + = ऑपरेटर को कॉल करता है, लेकिन यह विफल रहता है क्योंकि यह सुनिश्चित नहीं कर सकता है कि ऑपरेटर मौजूद है। सरल उपाय यह है कि इसे बाधा में निर्दिष्ट करें; सरल समाधान असंभव है क्योंकि ऑपरेटर स्थिर हैं और स्थिर तरीके एक इंटरफ़ेस में नहीं हो सकते हैं और (यहाँ समस्या है) बाधाओं को इंटरफेस के रूप में दर्शाया गया है।

सी # की जरूरत एक वास्तविक बाधा प्रकार है, सभी इंटरफेस भी बाधा बनेंगे, लेकिन सभी बाधाएं इंटरफेस नहीं होंगी तो आप ऐसा कर सकते हैं:

constraint CHasPlusEquals
{
    static CHasPlusEquals operator + (CHasPlusEquals a, CHasPlusEquals b);
}

T SumElements<T>(T initVal, T[] values) where T : CHasPlusEquals
{
    foreach (var v in values)
    {
        initVal += v;
    }
}

सभी संख्यात्मक प्रकारों को लागू करने के लिए IArithmetic बनाने के बारे में पहले से ही बहुत सारी बातें की जा चुकी हैं, लेकिन दक्षता के बारे में चिंता है, क्योंकि एक बाधा एक बहुरूपिक निर्माण नहीं है, एक CArithmetic बाधा बनाने से उस समस्या का समाधान होगा।


C # में ऑपरेटर स्थिर हैं, इसलिए यह अभी भी समझ में नहीं आता है।
जॉन सॉन्डर्स

उस बिंदु पर, बाधा यह सत्यापित करती है कि TYPE (उदाहरण के लिए) के पास + ऑपरेटर (और एक्सटेंशन + + ऑपरेटर) है और टेम्पलेट को जेनरेट करने की अनुमति देता है, तब जब वास्तविक टेम्प्लेट प्रतिस्थापन का उपयोग की जाने वाली वस्तु की गारंटी दी जाती है एक प्रकार जिसमें उस ऑपरेटर (या अन्य स्थिर विधि है।) तो आप कह सकते हैं: SumElements <int> (0, 5); जो इसे तात्कालिक कर देगा: SumElements (int initVal, int [] मान) {foreach (मूल्यों में var v) {initVal + = v; }}, जो निश्चित रूप से, सही अर्थ है
जेरेमी सोरेंसन

1
याद रखें यह कोई टेम्प्लेट नहीं है। यह जेनरिक है, जो C ++ टेम्प्लेट के समान नहीं है।
जॉन सॉन्डर्स

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

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

3

क्योंकि इंटरफ़ेस वंशानुक्रम संरचना में हैं, और स्थैतिक विधियाँ अच्छी तरह से विरासत में नहीं मिलती हैं।


3

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

इस बात पर अंतहीन बहस होगी कि क्या यह मायने रखता है, जो कि सबसे अच्छा अभ्यास है और क्या प्रदर्शन के मुद्दे इसे एक या दूसरे तरीके से कर रहे हैं। बस इसका समर्थन नहीं करके C # हमें इसके बारे में चिंता करने से बचाता है।

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


दिलचस्प है, VB.Net में दोनों प्रकार के विज्ञापन इंस्टेंस द्वारा एक स्थिर विधि को कॉल करना काफी संभव है (भले ही आईडीई बाद वाले मामले में चेतावनी देता है)। यह एक समस्या नहीं है। आप अनुकूलन के बारे में सही हो सकते हैं।
क्रामि

3

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


यह एक दिलचस्प पीओवी है, और संभवतः वह है जिसे सी # डिजाइनरों ने ध्यान में रखा था। मैं अब से अलग तरीके से स्थैतिक सदस्यों के बारे में सोचूंगा।
क्रामि

3

एक उदाहरण देने के लिए जहां मैं इंटरफ़ेस विधियों के स्थिर कार्यान्वयन को याद कर रहा हूं या मार्क ब्रैकेट ने "तथाकथित प्रकार की विधि" के रूप में पेश किया है:

डेटाबेस स्टोरेज से पढ़ते समय, हमारे पास एक जेनेरिक डेटाटेबल क्लास होती है जो किसी भी स्ट्रक्चर की टेबल से रीडिंग को हैंडल करती है। सभी तालिका विशिष्ट जानकारी को एक वर्ग प्रति तालिका में रखा जाता है जो DB से एक पंक्ति के लिए डेटा रखती है और जिसे IDataRow इंटरफ़ेस को लागू करना चाहिए। IDataRow में शामिल डेटाबेस से पढ़ने के लिए तालिका की संरचना का वर्णन है। DataTable को DB से पढ़ने से पहले IDataRow से डेटास्ट्रेक्चर के लिए पूछना चाहिए। वर्तमान में ऐसा दिखता है:

interface IDataRow {
  string GetDataSTructre();  // How to read data from the DB
  void Read(IDBDataRow);     // How to populate this datarow from DB data
}

public class DataTable<T> : List<T> where T : IDataRow {

  public string GetDataStructure()
    // Desired: Static or Type method:
    // return (T.GetDataStructure());
    // Required: Instantiate a new class:
    return (new T().GetDataStructure());
  }

}

GetDataStructure को पढ़ने के लिए प्रत्येक तालिका के लिए केवल एक बार आवश्यक है, एक और उदाहरण के लिए तत्काल ओवरहेड न्यूनतम है। हालाँकि, इस मामले में यहाँ अच्छा होगा।


1

FYI करें: आप इंटरफ़ेस के लिए विस्तार विधियाँ बनाकर जैसा चाहें वैसा व्यवहार प्राप्त कर सकते हैं। विस्तार विधि एक साझा, गैर-दुर्बल स्थैतिक व्यवहार होगा। हालाँकि, दुर्भाग्य से, यह स्थिर विधि अनुबंध का हिस्सा नहीं होगी।


1

इंटरफेस परिभाषित उपलब्ध कार्यक्षमता के सार सेट हैं।

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

यदि विधियों को स्थैतिक के रूप में परिभाषित किया गया था, तो इंटरफ़ेस को लागू करने वाला वर्ग उतना एनकैप्सुलेट नहीं होगा जितना कि हो सकता है। एनकैप्सुलेशन ऑब्जेक्ट ओरिएंटेड डिज़ाइन के लिए प्रयास करने के लिए एक अच्छी बात है (मैं इसमें क्यों नहीं जाऊंगा, आप इसे यहाँ पढ़ सकते हैं: http://en.wikipedia.org/wiki/Object-oriented )। इस कारण से, इंटरफ़ेस में स्थिर विधियों की अनुमति नहीं है।


1
हां, इंटरफ़ेस घोषणा में एक स्थिर मूर्खतापूर्ण होगा। एक वर्ग को एक निश्चित तरीके से इंटरफ़ेस को लागू करने के लिए मजबूर नहीं किया जाना चाहिए। हालाँकि, C # गैर-स्टैटिक विधियों का उपयोग करके इंटरफ़ेस को लागू करने के लिए एक वर्ग को प्रतिबंधित करता है। इसका कोई मतलब भी है क्या? क्यों?
क्राम्ति

आप कीवर्ड 'स्टेटिक' का उपयोग नहीं कर सकते। हालांकि कोई प्रतिबंध नहीं है क्योंकि आपको स्टैटिक कीवर्ड की जरूरत नहीं है कि वह एक ऐसी विधि लिख दे जो वैधानिक रूप से व्यवहार करती हो। बस एक ऐसी विधि लिखें जो अपने किसी भी ऑब्जेक्ट के सदस्य तक नहीं पहुंचती है, तो यह एक स्थिर विधि की तरह ही व्यवहार करेगी। तो, प्रतिबंध है।
स्कॉट लैंगहम

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

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

1

स्टेटिक कक्षाएं ऐसा करने में सक्षम होना चाहिए ताकि उन्हें उदारतापूर्वक उपयोग किया जा सके। मुझे वांछित परिणाम प्राप्त करने के लिए एक सिंगलटन को लागू करने के बजाय लागू करना था।

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


1

अधिकांश लोग यह भूल जाते हैं कि OOP क्लासेस ऑब्जेक्ट्स भी हैं, और इसलिए उनके पास मैसेज हैं, जो किसी कारण से c # "स्टैटिक मेथड" को कहते हैं। तथ्य यह है कि अंतर वस्तुओं और वर्ग की वस्तुओं के बीच अंतर मौजूद है, केवल भाषा में दोष या कमियों को दर्शाता है। आशावादी के बारे में ग # हालांकि ...


2
समस्या यह है कि यह सवाल "ओओपी" के बारे में नहीं है। यह "C #" के बारे में है। C # में, "संदेश" नहीं हैं।
जॉन सॉन्डर्स

1

यहाँ ठीक है एक 'प्रकार विधि' की आवश्यकता का एक उदाहरण है। मैं कुछ स्रोत XML के आधार पर कक्षाओं में से एक सेट बना रहा हूं। इसलिए मैंने ए

  static public bool IsHandled(XElement xml)

फ़ंक्शन जो प्रत्येक वर्ग को बदले में कहा जाता है।

फ़ंक्शन स्थिर होना चाहिए अन्यथा हम अनुचित वस्तुओं को बनाने में समय बर्बाद करते हैं। जैसा कि @ इयान बॉयडे बताते हैं कि यह एक कारखाना वर्ग में किया जा सकता है, लेकिन यह सिर्फ जटिलता जोड़ता है।

वर्ग कार्यान्वयनकर्ताओं को इसे लागू करने के लिए बाध्य करने के लिए इंटरफ़ेस में जोड़ना अच्छा होगा। यह महत्वपूर्ण ओवरहेड का कारण नहीं बनेगा - यह केवल एक संकलन / लिंक समय की जाँच है और व्यवहार्य को प्रभावित नहीं करता है।

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

तो यह एक छोटी क्षमता है जो संतुलन पर संभवत: सबसे अच्छा है।


1

तथ्य यह है कि Microsoft द्वारा C # में एक स्थिर वर्ग को कार्यान्वित किया जाता है स्थैतिक तत्वों के साथ एक वर्ग का एक विशेष उदाहरण बनाना सिर्फ एक विषमता है कि स्थिर कार्यक्षमता कैसे प्राप्त की जाती है। यह एक सैद्धांतिक बात नहीं है।

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

यहाँ एक बहुत स्पष्ट उदाहरण है जहाँ स्थिर वर्गों के साथ इंटरफेस का उपयोग करने में सक्षम होना काफी उपयोगी होगा:

public interface ICrudModel<T, Tk>
{
    Boolean Create(T obj);
    T Retrieve(Tk key);
    Boolean Update(T obj);
    Boolean Delete(T obj);
}

वर्तमान में, मैं स्टैटिक क्लासेस लिखता हूँ, जिसमें ये विधियाँ शामिल हैं कि बिना किसी जाँच के यह सुनिश्चित हो कि मैं कुछ भी नहीं भूल पाया हूँ। OOP से पहले प्रोग्रामिंग के बुरे दिनों की तरह है।


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

1

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

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


0

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


0

मुझे लगता है कि इस तथ्य पर सवाल उठ रहा है कि इस प्रकार की स्थिति के लिए C # को एक और कीवर्ड की आवश्यकता है। आप एक ऐसी विधि चाहते हैं जिसका वापसी मूल्य केवल उस प्रकार पर निर्भर करता है जिस पर इसे कहा जाता है। यदि अज्ञात है, तो आप इसे "स्थिर" नहीं कह सकते। लेकिन एक बार प्रकार ज्ञात हो जाने के बाद, यह स्थिर हो जाएगा। "अनारक्षित स्थैतिक" यह विचार है - यह अभी तक स्थिर नहीं है, लेकिन एक बार जब हम प्राप्त करने वाले प्रकार को जानते हैं, तो यह होगा। यह पूरी तरह से एक अच्छी अवधारणा है, यही वजह है कि प्रोग्रामर इसके लिए पूछते रहते हैं। लेकिन यह उस तरह से उपयुक्त नहीं था जिस तरह से डिजाइनर भाषा के बारे में सोचते थे।

चूंकि यह उपलब्ध नहीं है, मैंने नीचे दिखाए गए तरीके से गैर-स्थिर तरीकों का उपयोग करने के लिए लिया है। बिल्कुल आदर्श नहीं है, लेकिन मैं ऐसा कोई दृष्टिकोण नहीं देख सकता जो अधिक समझ में आए, कम से कम मेरे लिए नहीं।

public interface IZeroWrapper<TNumber> {
  TNumber Zero {get;}
}

public class DoubleWrapper: IZeroWrapper<double> {
  public double Zero { get { return 0; } }
}

0

ऑब्जेक्ट ओरिएंटेड कॉन्सेप्ट इंटरफ़ेस के अनुसार कक्षाओं द्वारा कार्यान्वित किया जाता है और ऑब्जेक्ट का उपयोग करके इन कार्यान्वित फ़ंक्शन (या विधियों) तक पहुंचने का अनुबंध करता है।

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


0

सैद्धांतिक रूप से ऐसा कोई कारण नहीं है कि कोई इंटरफ़ेस एक अनुबंध को परिभाषित नहीं कर सकता है जिसमें स्थिर तरीके शामिल हैं।

वर्तमान सी # भाषा कार्यान्वयन के लिए, प्रतिबंध एक आधार वर्ग और इंटरफेस की विरासत के भत्ते के कारण है। यदि "क्लास SomeBaseClass" इम्प्लीमेंट "इंटरफ़ेस ISomeInterface" और "क्लास SomeDerivedClass: SomeBaseClass, ISomeInterface" भी इंटरफ़ेस को लागू करता है, तो एक इंटरफ़ेस विधि को लागू करने के लिए एक स्थिर विधि विफल हो जाएगी क्योंकि एक स्टैटिक विधि एक इंस्टेंस विधि के रूप में एक ही हस्ताक्षर नहीं कर सकती है (जो होगा) इंटरफ़ेस को लागू करने के लिए बेस क्लास में मौजूद रहें)।

एक स्थिर वर्ग कार्यात्मक रूप से एक सिंगलटन के समान होता है और क्लीनर सिंटैक्स के साथ सिंगलटन के समान उद्देश्य को पूरा करता है। चूंकि एक सिंगलटन एक इंटरफ़ेस को लागू कर सकता है, स्टेटिक्स द्वारा इंटरफ़ेस कार्यान्वयन वैचारिक रूप से मान्य है।

इसलिए यह उदाहरण के लिए C # नाम संघर्ष की सीमा तक सीमित हो जाता है और विरासत में समान नाम के स्थिर तरीकों के लिए। ऐसा कोई कारण नहीं है कि स्थिर विधि अनुबंध (इंटरफेस) का समर्थन करने के लिए C # को "अपग्रेड" नहीं किया जा सका।


-1

जब एक वर्ग एक इंटरफ़ेस लागू करता है, तो यह इंटरफ़ेस सदस्यों के लिए उदाहरण बना रहा है। हालांकि एक स्थिर प्रकार में एक उदाहरण नहीं होता है, एक इंटरफ़ेस में स्थिर हस्ताक्षर होने का कोई मतलब नहीं है।

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