2010-03-04 10 views
37

मैं समझता हूं कि इंटरफेस अनुबंध हैं और कोई भी परिवर्तन (यहां तक ​​कि जोड़) किसी भी आश्रित कोड को तोड़ता है। हालांकि, मैंने शपथ ली थी कि मैंने कुछ समय पहले पढ़ा था कि हाल ही में .NET संस्करणों में से एक (3, 3.5 ??) ने एक नई विशेषता को जोड़ा जो नए इंटरफ़ेस सदस्यों पर लागू किया जा सकता था। इस विशेषता ने वर्जनिंग और/या सदस्यों को वैकल्पिक बनाने की अनुमति दी। यह कुछ ऐसा होता:सी # वैकल्पिक तरीकों के साथ इंटरफेस

interface ITest 
{ 
    void MethodOne(); 

    [InterfaceVersion(2)] 
    void MethodTwo(); 
} 

मैंने इसके लिए उच्च और निम्न देखा है लेकिन इसे ढूंढने के लिए प्रतीत नहीं होता है। मैं सोच रहा हूं कि क्या मैं बस जो भी सोचता हूं उसे गलत समझा जाता हूं और ऐसी कोई बात नहीं है। क्या किसी के पास कोई अंतर्दृष्टि है?

+0

ठीक है, भारी वोट "नहीं, लेकिन ..." रहा है। इस प्रकार मैं इसे लंबे समय तक दोषी ठहराऊंगा और मैं थक गया हूं। :) –

+0

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

+0

उपभोक्ता को यह निर्दिष्ट करना होगा कि यह किस संस्करण का उपयोग कर रहा है, लेकिन फिर आपको कुछ कठिनाइयां हैं। क्या होगा यदि आपका कोड दोनों संस्करणों का उपयोग करता है? तो आपके पास कक्षा 1 है: [इंटरफेसवर्सन (1)] आईटेस्ट और कक्षा 2: [इंटरफेसवर्सन (2)] आईटीएस्ट। फिर आप करते हैं "अगर (कक्षा 2 आईटीएस्ट है)" ... लेकिन कौन सा? ऐसा लगता है कि एक बार जब आप एक ही स्थान पर विशेषता का उपयोग करते हैं, तो आपको इसे हर जगह उपयोग करना होगा। कंपाइलर को यह सब ट्रैक रखना होगा और इसे आप पर मजबूर करना होगा। यह ITest1, ITest2 करने में आसान हो सकता है ... तो यह नई "सुविधा" विशेषता वास्तव में इसे और खराब कर सकती है। :) –

उत्तर

41

आप दो इंटरफेस बनाना चाहिए:

interface ITest 
{ 
    void MethodOne(); 
} 

interface ITest2 : ITest 
{ 
    void MethodTwo(); 
} 

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

+0

मैंने देखा है कि COM दिनों में किया गया है। कुछ सालों के बाद जो एक लंबी सूची बन सकता है, लेकिन तब तक आप अपने एपीआई को फिर से डिजाइन करना चाहेंगे। –

+0

लेकिन यह उस उद्देश्य को हरा देता है जिसमें एक सामान्य अनुबंध सही होता है। मेरा मतलब है कि मैं बदसूरत कलाकारों के बिना एक समारोह में इन दोनों इंटरफेस (आईटेस्ट, आईटीएस्ट 2) को लागू करने वाली ऑब्जेक्ट को पास करने में सक्षम होना चाहिए। मुझे लगता है कि इस मामले में एक ही इंटरफ़ेस (जो सभी विधियों को घेरता है) आईटीएस्ट 2 और जो लोग केवल कुछ फ़ंक्शंस को कार्यान्वित करना चाहते हैं उन्हें बाकी के लिए NotSupportedException को फेंकना होगा जैसा कि यहां बताया गया है https://stackoverflow.com/a/ 4566711/3921536 – router

+0

समर्थित नहीं किया गया अपवाद/नहीं कार्यान्वित इंटरफ़ेस के मामले में अपवाद आपके द्वारा चालू किए जाने वाले अंतिम बैक-अप समाधान होना चाहिए, जब आपके लिए कोड बनाने की कोई अन्य साधन आपके लिए काम नहीं करती है। यह कहने के बराबर है "निश्चित रूप से, मैं कल आपको काम करने के लिए ड्राइव कर सकता हूं" और फिर एक साइकिल के साथ चालू करने के लिए "मूर्ख तुम!"। एक इंटरफ़ेस को अनुबंध के रूप में माना जाना चाहिए, अगर आप कहते हैं कि आप इसका समर्थन करते हैं, तो आप ** वास्तव में ** इसका समर्थन करना चाहिए। ऐसे कुछ मामले हैं जहां डेवलपर्स ने NotSupportedException का उपयोग करके उचित ठहराना है लेकिन इसे केवल अंतिम उपाय के रूप में उपयोग किया जाना चाहिए। –

4

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

public abstract class Test 
{ 
    public abstract void MethodOne(); 
    public virtual void MethodTwo() { } 
} 

इस उपयोगकर्ता तय करने के लिए किया जाए या नहीं वे जब टेस्ट से इनहेरिट, जबकि methodone का अधिभावी मजबूर कर MethodTwo ओवरराइड करना चाहते अनुमति होगी।

+0

कभी-कभी, यह समाधान, निश्चित रूप से गलत नहीं होने पर, एकाधिक विरासत की कमी के लिए मौजूदा कोड तोड़ सकता है। –

+0

हां, यह किल्फोफर ने जो कहा है उसके समान है। मुझे इसके बारे में पता है, लेकिन मैं आमतौर पर बेस क्लास से बचता हूं जब तक कि मेरी नई कक्षा "बेस" बेसक्लास (बनाम "में" ISOMething) न हो। –

5

.NET ढांचे में ऐसी कोई विशेषता नहीं है।

+1

मैं विशेष रूप से http://msdn.microsoft.com/en-us/library/aa311259%28VS.71%29.aspx पर प्रत्येक विशेषता के माध्यम से चला गया और बाहर खड़ा एक नहीं मिला। मुझे अभी आपके साथ सहमत होना होगा। –

10

मैंने ऐसी कोई विशेषता नहीं देखी है, लेकिन मुझे लगता है कि यह संभव है। This article एमएसडीएन पर overrides और new कीवर्ड के उपयोग के माध्यम से संस्करण का वर्णन करता है।

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

एक इंटरफेस बनाने का उदाहरण है कि एक और की आवश्यकता है:

public interface IMyInterface 
{ 
    void FirstMethod(); 
} 

public interface IMySecondInterface : IMyInterface 
{ 
    void SecondMethod(); 
} 

वंशानुक्रम का उपयोग संगतता बनाए रखने के लिए का उदाहरण:

public class MyBase 
{ 
    public virtual string Meth1() 
    { 
     return "MyBase-Meth1"; 
    } 
    public virtual string Meth2() 
    { 
     return "MyBase-Meth2"; 
    } 
    public virtual string Meth3() 
    { 
     return "MyBase-Meth3"; 
    } 
} 

class MyDerived : MyBase 
{ 
    // Overrides the virtual method Meth1 using the override keyword: 
    public override string Meth1() 
    { 
     return "MyDerived-Meth1"; 
    } 
    // Explicitly hide the virtual method Meth2 using the new 
    // keyword: 
    public new string Meth2() 
    { 
     return "MyDerived-Meth2"; 
    } 
    // Because no keyword is specified in the following declaration 
    // a warning will be issued to alert the programmer that 
    // the method hides the inherited member MyBase.Meth3(): 
    public string Meth3() 
    { 
     return "MyDerived-Meth3"; 
    } 

    public static void Main() 
    { 
     MyDerived mD = new MyDerived(); 
     MyBase mB = (MyBase) mD; 

     System.Console.WriteLine(mB.Meth1()); 
     System.Console.WriteLine(mB.Meth2()); 
     System.Console.WriteLine(mB.Meth3()); 
    } 
} 
+0

मुझे इस विधि से अवगत था, लेकिन यह इंटरफेस का उपयोग नहीं कर रहा है। मुझे "नहीं" कहने के इतने सारे जवाब प्राप्त हुए हैं, कि मैंने इसे गलत तरीके से पढ़ा होगा। –

+0

बेस क्लास मूल इंटरफ़ेस – Kilhoffer

+0

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

0

आप partial methods (MSDN) के बारे में सोच हो सकती है।

+0

नहीं, लेकिन मुझे यह भी नहीं पता था कि आप ऐसा कर सकते हैं। आंशिक कक्षाएं पूरी तरह से उपयोग की जाती हैं (डिजाइनर बनाम उपयोगकर्ता द्वारा जेनरेट कोड)।मैंने इस मंच के माध्यम से सी #/एनईटी पढ़ने में इतने सारे "किनारे के मामलों/विशेषताओं" के बारे में सीखा है! –

2

मैं हाल ही में स्थिति है जहाँ कई विरासत का निर्धारित कमी मुझे न करे एक अमूर्त वर्ग में एक मौजूदा इंटरफेस को बदलने के लिए में था, और अपने आप को एक विस्तार समाधान के साथ पाया:

interface IFoo { 
      int RowCount(); 
    } 

    static class _FooExtensions { 
      public static bool HasAnyRows (this IFoo foo) { 
        return foo.RowCount() > 0; 
      } 
    } 

इस तरह आप एक प्रदान कर सकते हैं यदि आपके अमूर्त विधि को अन्य कार्यों के संदर्भ में परिभाषित किया जा सकता है तो डिफ़ॉल्ट संस्करण।

+0

ठीक है, यह एक सहायक वर्ग की तरह होगा। पहले मैंने सोचा था कि आप विस्तार विधियों का जिक्र कर रहे थे जो कुछ परिस्थितियों में अच्छी तरह से काम करेंगे (LINQ, आदि)। एक चीज जो खड़ी हुई, "यह इफू फू" क्या करती है? मैंने इसे एक कन्स्ट्रक्टर से दूसरे में कूदने सहित इंस्टेंस सदस्यों तक पहुंचने के लिए उपयोग किया है, लेकिन मैंने इसे कभी भी इस तरह इस्तेमाल नहीं किया है। –

+0

@ नेल्सन: यह एक विस्तार विधि है। उनका उपयोग केवल LINQ के लिए नहीं किया जाता है। –

+0

ओह, मेरे बुरे। मैंने एक या दो बार एक विस्तार विधि का उपयोग किया, लेकिन पूर्ण वाक्यविन्यास को याद नहीं किया। मैं समझता हूं कि इसमें कई उपयोग हैं। यह अभी भी तकनीकी रूप से एक "सहायक" वर्ग है, लेकिन वास्तव में एक इंटरफ़ेस को लागू करने या कक्षा से प्राप्त किए बिना ओओपी अवधारणाओं को बनाए रखना। कभी-कभी बहुत आसान। –

1

आप

interface ITest 
{ 
    void MethodOne(); 

    [InterfaceVersion(2)] 
    void MethodTwo(); 
} 



[AttributeUsage(AttributeTargets.All)] 
public class InterfaceVersion : System.Attribute 
{ 
    public readonly int N; 

    public InterfaceVersion(int n) 
    { 
     this.N = n; 
    } 
} 

की तरह कुछ पढ़ा होगा लेकिन मुझे नहीं लगता कि MethodTwo वैकल्पिक के कार्यान्वयन कर सकता है।

संपादित करें:

मैं सिर्फ कोड कि यह वास्तव में MethodTwo वैकल्पिक के कार्यान्वयन नहीं है चलाकर पता चला।

+0

ठीक है, संकलक इसे वैकल्पिक होने की अनुमति नहीं देगा, जब तक कि माइक्रोसॉफ्ट विशेष रूप से एकीकृत न हो (जैसे [अप्रचलित()], आदि)। फिर भी मुझे यकीन नहीं है कि यह कैसे काम करेगा और ऐसा करना असंभव हो सकता है। –

+0

आपके संपादन के लिए: हाँ, यह केवल एक कस्टम विशेषता है जो नाम में "संस्करण" होता है। इसे "इंटरफेस नम्बर" भी कहा जा सकता है और वास्तव में वही प्रभाव पड़ सकता है। –

6

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

+0

मुझे नहीं लगता कि यह था, लेकिन दिलचस्प लगता है। क्या आपको किसी भी मौके से कुछ और जानकारी (उदाहरण, इत्यादि) का लिंक है? –

+1

@ नेल्सन: http://blogs.msdn.com/samng/archive/2010/01/24/the-pain-of-deploying-primary-interop-assemblies.aspx –

संबंधित मुद्दे