2017-04-20 8 views
21

मैं वास्तव में कुछ इस तरह की जरूरत है:मनुष्य और सेटर अलग इंटरफेस से आ रही

: जब मैं IReadableWritableVar.Value उपयोग करने के लिए मैं, त्रुटियों संकलन मिल जब तक कि मैं स्पष्ट रूप से आधार इंटरफेस करने के लिए डाली यहाँ की तरह कोशिश

interface IReadableVar 
{ 
    object Value { get; } 
} 

interface IWritableVar 
{ 
    object Value { set; } 
} 

interface IReadableWritableVar : IReadableVar, IWritableVar 
{ 
} 

हालांकि

static void Main() 
{ 
    IReadableWritableVar var = null; 
    var t = var.Value; // <-- CS0229: Ambiguity between 'IReadableVar.Value' and 'IWritableVar.Value' 
    var.Value = null; // <-- CS0229: Ambiguity between 'IReadableVar.Value' and 'IWritableVar.Value' 

    var v = ((IReadableVar)var).Value; // compiles fine 
    ((IWritableVar)var).Value = null; // compiles fine 
} 

मुझे इन त्रुटियों को क्यों प्राप्त होता है हालांकि सबकुछ संकलक को स्पष्ट होना चाहिए? कास्टिंग के अलावा इस समस्या को ठीक करने का कोई तरीका है (आवेदन में सैकड़ों स्थान)?

अपडेट: यह सुझाव दिया गया था कि यह Implementing 2 Interfaces with 'Same Name' Properties का डुप्लिकेट है लेकिन यह मामला थोड़ा अलग है क्योंकि इंटरफेस में कोई विरासत नहीं है। वैसे भी, समस्या अब हल हो गई है - स्वीकृत उत्तर देखें।

+0

मुझे लगता है कि संकलक कि में नहीं बनाया गया है गेटटर या सेटर –

+0

के आधार पर विभिन्न इंटरफेस में समान गुणों के बीच अंतर करने का तरीका [समान नाम 'गुणों के साथ 2 इंटरफेस लागू करना] का संभावित डुप्लिकेट (http://stackoverflow.com/questions/532148/implementing-2-interfaces-with- समान नाम-गुण) – PJvG

+2

ध्यान दें कि 'IWritableVar' संदिग्ध है, क्योंकि केवल-लिखने वाले गुणों पर संदेह है। कोई भी कॉलर जो संपत्ति लिख सकता है, शायद इसे पढ़ने में भी सक्षम होना चाहिए, और जहां यह समझ में नहीं आता है, तो शायद आप एक विधि चाहते हैं, न कि संपत्ति। –

उत्तर

16

एक संभावित समाधान, इस तरह अपने इंटरफेस IReadableWritableVar को संशोधित किया जा सकता है:

interface IReadableWritableVar : IReadableVar, IWritableVar 
{ 
    new object Value { get; set; } 
} 

लेकिन में रखना मेरे कि एक वैध कार्यान्वयन होना चाहिए:

class ReadableWritableVar : IReadableWritableVar 
{ 
    public object Value 
    { 
     get { throw new NotImplementedException(); } 
     set { throw new NotImplementedException(); } 
    } 

    object IWritableVar.Value 
    { 
     set { throw new NotImplementedException(); } 
    } 

    object IReadableVar.Value 
    { 
     get { throw new NotImplementedException(); } 
    } 
} 

एक और अधिक ठोस उदाहरण:

class ReadableWritableVar : IReadableWritableVar 
{ 
    public object Value 
    { 
     get { return ((IReadableVar)this).Value; } 
     set { ((IWritableVar)this).Value = value; } 
    } 

    object _val; 

    object IWritableVar.Value { set { _val = value; } } 

    object IReadableVar.Value => _val; 
} 

या इससे भी बेहतर:

class ReadableWritableVar : IReadableWritableVar 
{ 
    public object Value { get; set; } 

    object IWritableVar.Value { set { Value = value; } } 

    object IReadableVar.Value => Value; 
} 
+1

मैं सोच रहा हूं कि इसका उपयोग कैसे किया जाएगा? –

+2

बस एक नोट: आपको स्पष्ट कार्यान्वयन की आवश्यकता नहीं है। 'कक्षा पठनीय योग्यता: आईआरएडेबल WritableVar { सार्वजनिक वस्तु मूल्य {प्राप्त करें; सेट; } } 'ठीक संकलित करता है। – vyrp

+1

बस 'नई मूल्य' संपत्ति को 'IReadableWritableVar' में जोड़कर मेरे लिए समस्या हल हो गई। इसे लागू करने वाला वर्ग गैर-स्पष्ट अनुकरण कर रहा था। यह एक कामकाज है लेकिन बहुत अच्छा काम करता है - बहुत बहुत धन्यवाद। – Arek

0

इंटरफ़ेस के सार वर्ग आइसटेड का उपयोग करके आपकी समस्या का समाधान होगा।

public abstract class ReadableWritableVar : IReadableVar, IWritableVar 
{ 
    public object Value { get; set; }  
} 
+1

लेकिन अगर इसे इंटरफ़ेस नहीं है, तो इसे 'इरेडेबल योग्य संपादन' कहें, इसे या तो 'पठनीय योग्यनीय' या 'सार पढ़ने योग्य WritableVar' कहें। – PJvG

+0

@ पीजेवीजी, आप सही हैं। धन्यवाद – daniell89

+0

दुर्भाग्य से यह एक इंटरफ़ेस होना चाहिए, और इसे लागू करने वाली कक्षा उनमें से अधिक लागू करती है। – Arek

3

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

जब हमने इन इंटरफेस में से किसी एक को डाला तो दूसरा सदस्य चला गया और कोई त्रुटि नहीं हुई।

अगर हम लागू उन सदस्य के रूप में संकलक कि क्रियान्वयन का उपयोग करेगा कोई त्रुटि हो जाएगा:

class ReadableWritableVar : IReadableWritableVar 
{ 
    public object Value { get; set; } 
} 

var @var = new ReadableWritableVar(); 
var t = @var.Value; 

इसके अलावा, आप @Alessandro डी 'Andria के जवाब से एक स्पष्ट इंटरफेस सदस्यों कार्यान्वयन का उपयोग कर सकते यदि यह आवश्यक है कि आप इंटरफ़ेस का उपयोग करते हैं और कक्षा नहीं।

+0

ये केवल आंतरिक तरीके हैं, लेकिन मुझे लगता है कि दो अलग-अलग तरीकों से। यही कारण है कि मुझे समझ में नहीं आता कि संकलक इस तरह से क्यों व्यवहार करता है। अगर मैं किसी संपत्ति के बजाय दो विधियों (सेटर और गेटर) का उपयोग करता हूं तो समस्या मौजूद नहीं होगी। – Arek

7

दिलचस्प सवाल। मुझे लगता है कि विस्तार के तरीके इस मामले में मदद करेंगे।

public static class Extension 
{ 
    public static object GetValue(this IReadableVar v) 
    { 
     return v.Value; 
    } 

    public static void SetValue(this IWritableVar v, object value) 
    { 
     v.Value = value; 
    } 
} 

आप इसे उपयोग करने के लिए कोड को बदलने की जरूरत:

IReadableWritableVar variable = null; 
var t = variable.GetValue(); 
variable.SetValue(null); 

विस्तार विधि आपके लिए डाली है।

+0

यह दिलचस्प दृष्टिकोण है, लेकिन ऐसे मामले में मैं केवल 'SetValue' और 'GetValue' विधियों का उपयोग करता हूं और पूरी तरह से संपत्ति से छुटकारा पाता हूं। दुर्भाग्यवश संपत्ति की आवश्यकता है क्योंकि इसे डब्ल्यूपीएफ बाइंडिंग सिस्टम के साथ काम करना है। – Arek

0

एक संभावित विकल्प स्पष्ट (जावा शैली) का उपयोग हो और एक संपत्ति के बजाय तरीकों स्थापित करने के लिए है:

interface IReadableVar 
{ 
    object GetValue(); 
} 

interface IWritableVar 
{ 
    void SetValue(object value); 
} 

interface IReadableWritableVar : IReadableVar, IWritableVar 
{ 

} 

उपयोग तो हो जाता है:

static void Main(string[] args) 
{ 
    IReadableWritableVar aVar = null; 

    var t = aVar.GetValue(); 
    aVar.SetValue(null); 
} 
+0

दुर्भाग्यवश यह एक संपत्ति होनी चाहिए क्योंकि डब्ल्यूपीएफ बाइंडिंग सिस्टम जो इसका उपयोग करने जा रहा है। – Arek

+1

आपने कहा कि यह हार्डवेयर पर जाता है, सीधे डब्ल्यूपीएफ में बाइंडिंग से? आपको यहां और परतों की आवश्यकता है। –

+0

@ ब्रायन बॉटर अच्छा, वास्तव में मेरे पास और परतें हैं। लेकिन अभी भी कुछ ऐसा जो हार्डवेयर स्तर पर लिखा जा सकता है, इन परतों में केवल एक लिखने योग्य संपत्ति है ... – Arek

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