मैं इंटरफ़ेस पर स्थिर तरीके कैसे लागू कर सकता हूं?


92

मेरे पास 3rd पार्टी C ++ DLL है जिसे मैं C # से कॉल करता हूं।

विधियाँ स्थिर हैं।

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

संशोधक 'स्थिर' इस मद के लिए मान्य नहीं है

MyMethod cannot be accessed with an instance reference; qualify it with a type name instead

मैं इस अमूर्तता को कैसे प्राप्त कर सकता हूं?

मेरा कोड इस तरह दिखता है

private IInterfaceWithStaticMethods MyInterface;

public MyClass(IInterfaceWithStaticMethods myInterface)
{
  this.MyInterface = myInterface;
}

public void MyMethod()
{
  MyInterface.StaticMethod();
}

3
हो सकता है कि आप इसे विस्तार विधियों के साथ कर सकते हैं: stackoverflow.com/questions/1243921/…
hcb

जवाबों:


47

आप C # में इंटरफ़ेस पर स्थिर सदस्यों को परिभाषित नहीं कर सकते। एक इंटरफ़ेस उदाहरणों के लिए एक अनुबंध है

जैसा कि आप वर्तमान में हैं, मैं इंटरफ़ेस बनाने की सलाह दूंगा, लेकिन स्थिर कीवर्ड के बिना। फिर एक वर्ग बनाएं StaticIInterfaceजो इंटरफ़ेस को लागू करता है और स्थिर C ++ विधियों को कॉल करता है। यूनिट टेस्टिंग करने के लिए, एक अन्य क्लास बनाएं FakeIInterface, जो कि इंटरफ़ेस को लागू करता है, लेकिन आपको अपने यूनिट टेस्ट को संभालने की आवश्यकता है।

एक बार जब आपके पास इन 2 वर्गों को परिभाषित कर दिया जाता है, तो आप अपने पर्यावरण के लिए आवश्यक एक बना सकते हैं, और इसे पास करने वाले के पास भेज सकते हैं MyClass


64
-1 कहने के लिए An interface is a contract, not an implementation.- यह सच है, लेकिन यहां पूरी तरह से अप्रासंगिक ( गैर अनुक्रमिक ) है, क्योंकि स्थैतिक विधि स्वयं कार्यान्वयन का हिस्सा नहीं है - कार्यान्वयन, परिभाषा के अनुसार, डेटा पर आधारित है , जो बदले में, स्थिर सदस्यों के लिए दुर्गम हैAn interface type definition can define and implement static methods (see §8.4.3) since static methods are associated with the interface type itself rather than with any value of the type.- ध्यान रखें कि staticसदस्य आमतौर पर उपयोगिता विधियां हैं

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

1
मैं आंशिक रूप से सहमत हूं कि An interface is a contract, not an implementationबेकार है, कभी-कभी थोड़ा संवेदीकरण वास्तव में मदद करता है। और मैं पूरी तरह से सहमत हूं static method is not a part of implementation itself , स्थैतिक तरीकों का कार्यान्वयन होता है, वे केवल कार्यान्वयन का हिस्सा बनते हैं यदि किसी अन्य विधि के कार्यान्वयन में कार्यान्वयन के रूप में उपयोग किया जाता है। हालाँकि मेरा शब्दकोश जो सीखा है, उस पर आधारित है, जहाँ तक मैं जानता हूँ, शब्दावली वास्तव में प्रोग्रामिंग भाषा के आधार पर भी भिन्न होती है। स्थैतिक तरीके खिचड़ी भाषा का इंटरफेस नहीं हैं क्योंकि वैसे भी केवल 1 कार्यान्वयन हो सकता है।
कॉफिडेवलपर्स

कल्पना कीजिए कि मेरे पास एक IPersonअनुबंध है जो बताता है कि GetCountryव्यक्ति के मूल देश का नाम देगा ... FrenchPersonसंस्थाओं को सभी "फ्रांस" GermanPersonकहेंगे और सभी "जर्मनी" कहेंगे, यह भी उपयोगी है जब विभिन्न प्रकार की संस्थाएं समान (डेटा) तालिका को साझा करती हैं, जैसे कि एमएस। Azure एक, कहते हैं Connection, Postऔर AzureTable Commentमें संग्रहीत हैं Users, इसलिए पेड़ संस्थाओं के पास एक साझा जानकारी है, स्थैतिक विधि IUsersहो सकती है GetTableName...
सर्ज

@vaxquis - IMHO, "इसका एक अनुबंध" प्रासंगिक होगा यदि वाक्य को फिर से शुरू किया गया था: forAn इंटरफ़ेस उदाहरणों के लिए एक अनुबंध है । स्थैतिक सदस्य प्रकार का हिस्सा हैं; यह प्रतिपादित वाक्य कहता है (सही ढंग से) कि उन्हें उदाहरण के अनुबंध में कोई मतलब नहीं है। इसलिए मुझे लगता है कि समस्या महज शब्दावलियों की है, न कि एक गैर क्रम की।
टूलमेकरसैट

112

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

आप क्या कर सकते हैं एक स्पष्ट इंटरफ़ेस कार्यान्वयन का उपयोग करें:

public interface IMyInterface
{
    void MyMethod();
}

public class MyClass : IMyInterface
{
    static void MyMethod()
    {
    }

    void IMyInterface.MyMethod()
    {
        MyClass.MyMethod();
    }
}

वैकल्पिक रूप से, आप केवल गैर-स्थैतिक तरीकों का उपयोग कर सकते हैं, भले ही वे किसी भी उदाहरण के विशिष्ट सदस्यों तक न पहुंचें।


18
किसी के लिए यह सोचकर कि कोई भी ऐसा क्यों करना चाहेगा, इसकी विशेष रूप से उपयोगी है जब इकाई लिखने / एकीकरण कोड के लिए एकीकरण परीक्षण जो स्थैतिक तरीकों को लागू करता है।
देजोमांडो

त्वरित तकनीक एपीआई को लागू करने के लिए इस तकनीक ने बहुत अच्छा काम किया जो डेटा को बनाए रखने के लिए आवश्यक था लेकिन डेटाबेस का उपयोग नहीं कर सकता था। कार्यान्वयन केवल इन-मेमोरी C # ऑब्जेक्ट्स के साथ काम कर रहा था, इसलिए डेटा को स्टोर करने के लिए कोई जगह नहीं थी, लेकिन एक स्थिर संपत्ति का उपयोग करके ईएफ कोर या SQLite का उपयोग करके इन-मेमोरी डेटाबेस की आवश्यकता कम हो गई।
gware

19

CLR में स्टेटिक सदस्य पूरी तरह से कानूनी हैं, सिर्फ C # नहीं।

आप कार्यान्वयन विवरण को लिंक करने के लिए IL में कुछ गोंद लागू कर सकते हैं।

निश्चित नहीं है कि क्या C # कंपाइलर उन्हें कॉल करने की अनुमति देगा?

देखें: 8.9.4 इंटरफ़ेस प्रकार की परिभाषा ECMA-335।

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

इसी प्रकार, एक इंटरफ़ेस प्रकार की परिभाषा अपने प्रकार के मूल्यों पर किसी भी तरीके के लिए कार्यान्वयन प्रदान नहीं करेगी। हालाँकि, एक इंटरफ़ेस प्रकार की परिभाषा हो सकती है - और आमतौर पर विधि अनुबंधों (विधि नाम और विधि हस्ताक्षर) को परिभाषित करती है जिन्हें समर्थन प्रकारों द्वारा लागू किया जाएगा। एक इंटरफ़ेस प्रकार की परिभाषा स्थिर तरीकों को परिभाषित और कार्यान्वित कर सकती है (देखें .38.4.3) क्योंकि स्थिर तरीके इंटरफ़ेस के प्रकार से जुड़े होते हैं बजाय किसी प्रकार के मूल्य के।


10
संदर्भ के लिए, CLS Rule 19: CLS-compliant interfaces shall not define static methods, nor shall they define fields.यह कहना है कि सीएलएस उपभोक्ताओं के लिए इस प्रकार के इंटरफेस को अस्वीकार करना ठीक है। मैंने एक साल पहले एक इंटरफ़ेस पर एक स्थिर विधि को कॉल करने की कोशिश की और सी # संकलक इसे संकलित नहीं करेगा।
क्रिस्टोफर Currens

आगे @ChristopherCurrens सीएलएस के बारे में ध्यान दें: Common Language Specification (CLS) is a set of basic language features that .Net Languages needed.... When there is a situation to communicate Objects written in different .Net Complaint languages , those objects must expose the features that are common to all the languages. यह समझ में आता है कि यदि सीएलएस विभिन्न .NET भाषाओं में इंटरऑपरेबिलिटी के बारे में है, और C # एक इंटरफ़ेस पर स्थिर सदस्यों की अनुमति नहीं देता है, तो CLS उन्हें भी मना कर देगा, जिसमें पुस्तकालयों को सुनिश्चित किया जा सके। अन्य .NET भाषाओं को C # से बुलाया जा सकता है।
साइमन टवेसी

17

आप c # 8 में स्थैतिक तरीकों को परिभाषित कर सकते हैं लेकिन आपको इसके लिए एक डिफ़ॉल्ट निकाय की घोषणा करनी चाहिए।

    public interface IMyInterface
    {
          static string GetHello() =>  "Default Hello from interface" ;
          static void WriteWorld() => Console.WriteLine("Writing World from interface");
    }

या यदि आप कोई डिफॉल्ट बॉडी नहीं रखना चाहते हैं तो बस एक अपवाद फेंक दें:

    public interface IMyInterface
    {
          static string GetHello() =>  throw new NotImplementedException() ;
          static void WriteWorld() => throw new NotImplementedException();
    }

ऐसा लगता है कि इंटरफेस में स्थैतिक सदस्य बहुत बेकार हैं क्योंकि आप इंटरफ़ेस उदाहरण द्वारा उन्हें एक्सेस नहीं कर सकते हैं। कम से कम C # 8.
Pavel Sapehin

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

5

आप इसे प्रतिबिंब के साथ आमंत्रित कर सकते हैं:

MyInterface.GetType().InvokeMember("StaticMethod", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, null);

5
और यदि आपके पास MyInterface का कोई उदाहरण नहीं है, तो आप "myInterface.GetType ()" के बजाय "typeOf (MyInterface)" का उपयोग कर सकते हैं।
रेन्नीपेट

उस समय एक अच्छे विचार की तरह लगता है, और मैं इसे प्रतिबिंब के माध्यम से करना जारी रख सकता हूं, लेकिन एक छोटी सी चेतावनी: यह अधिक समस्याग्रस्त हो जाता है यदि प्रोग्राम को इस तरह से बाधित किया जाता है तो विधि StaticMethod का नाम बदल जाता है।
RenniePet

1
@ RenniePet: आप आंशिक रूप से इसके बजाय nameof (StaticMethod) का उपयोग करके नाम बदलने वाले StaticMethod के साथ सौदा कर सकते हैं। यह नाम बदलने के तरीके पर निर्भर करता है कि यह एक ऑबफ्यूज़र के साथ मदद करता है। यदि आप इसे इस तरह करते हैं तो आपको कम से कम एक संकलन समय त्रुटि दिखाई देगी।
ब्रेंट रिटेनहाउस

प्रतिबिंब इस मामले के लिए भी चरम है
Stepan Ivanenko

3

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

interface IMonoid<T>
{
    static T Zero { get; }
    static T operator +(T t1, T t2);
}

public static T AddAll<T>(T[] ts) where T : IMonoid<T>
{
    T result = T.Zero;
    foreach (T t in ts) { result += t; }
    return result;
}

role IntAddMonoid extends int : IMonoid<int>
{
    public static int Zero => 0;
}

IntAddMonoid[] values = new int[] {1, 2, 4, 8, 16, 32};
int sixtyThree = AddAll<IntAddMonoid>(values); // == 63

अतिरिक्त संसाधन:

जेरेमी बाइट्स: C # 8 इंटरफ़ेस स्थिर सदस्य

संपादित करें

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


1

के रूप में क्यों आप एक अंतरफलक पर एक स्थिर विधि नहीं हो सकता है: क्यों नहीं # सी इंटरफ़ेस को लागू करने के लिए स्टेटिक तरीकों की अनुमति दें?

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

अर्थात

public static class MyStaticClass
{
    public static void MyStaticMethod()
    {...}
}

public interface IStaticWrapper
{
    void MyMethod();
}

public class MyClass : IStaticWrapper
{
    public void MyMethod()
    {
        MyStaticClass.MyStaticMethod();
    }
}

केवल इंटरफ़ेस का उपयोग करके स्थिर वर्ग के साथ इंटरफ़ेस का उपयोग करने का क्या लाभ है?
सेलेन

1

C # 8 अंतरंग पर स्थैतिक सदस्यों को अनुमति देता है

C # 8.0 के साथ शुरुआत, एक इंटरफ़ेस सदस्यों के लिए एक डिफ़ॉल्ट कार्यान्वयन को परिभाषित कर सकता है। यह सामान्य कार्यक्षमता के लिए एकल कार्यान्वयन प्रदान करने के लिए स्थैतिक सदस्यों को भी परिभाषित कर सकता है।

इंटरफ़ेस (C # संदर्भ)

उदाहरण के लिए

public interface IGetSomething
{
    public static string Something = "something";
}

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