2017-02-23 9 views
8

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

public interface IQuestion<T> 
{ 
    T Content { get; } 
} 

public interface IAnswer<T> 
{ 
    T Content { get; } 
    bool IsCorrect { get; } 
} 

और समस्या तब होती है जब हम टास्क बनाने:

interface ITask<TQuestion, TAnswer> 
{ 
    TQuestion Question { get; } 
    List<TAnswer> Answers { get; } 
} 

कैसे लिखने के लिए कि TQuestionIQuestion और TAnswer की उप-प्रकार होना चाहिए - IAnswer की उप-प्रकार?

मैं tryed है:

interface ITask<TQuestion, TAnswer> 
    where TQuestion : IQuestion<object> 
    where TAnswer : IAnswer<object> 

लेकिन जब मैं बनाया:

class TextQuestion : IQuestion<string> {...} 
class TextAnswer : IAnswer<string> {...} 

यह काम नहीं किया:

class TextTask : ITask<TextQuestion, TextAnswer> 

क्योंकि, वास्तव में, IQuestion<string> नहीं है IQuestion<object> से विरासत में मिला।

में जावा, मैं ITask सामान्य प्रकार के प्रतिबंध में वाइल्डकार्ड का उपयोग होता है, Kotlin में, ऊपर दृष्टिकोण काम किया होता।

लेकिन सी # का उपयोग करके इसे कैसे हल करें?

उत्तर

4

आप किसी तृतीय पैरामीटर की आवश्यकता होगी:

interface ITask<TQuestion, TAnswer, T> 
    where TQuestion : IQuestion<T> 
    where TAnswer : IAnswer<T> 

आप जानते हैं, IQuestion<string>IQuestion<object> से विरासत में मिला नहीं है, लेकिन इस तरह से आप TQuestion हो सकता है IQuestion<string> हो।


परिशिष्ट: होने TQuestionIQuestion<object> होना ही एक समस्या है क्योंकि IQuestionvariance परिभाषित नहीं है (हां, तो यह डिफ़ॉल्ट रूप से अपरिवर्तनीय है)। यदि आप नीचे दिखाए गए अनुसार परिभाषित करते हैं, तो आप IQuestion<object> का उपयोग कर सकते हैं (यह IAnswer के लिए भी जाता है)।

public interface IQuestion<out T> 
{ 
    T Content { get; } 
} 

public interface IAnswer<out T> 
{ 
    T Content { get; } 
    bool IsCorrect { get; } 
} 

interface ITask<TQuestion, TAnswer> 
    where TQuestion : IQuestion<object> 
    where TAnswer : IAnswer<object> 
{ 
    TQuestion Question { get; } 
    List<TAnswer> Answers { get; } 
} 
+1

दिलचस्प जवाब; जॉन स्कीट ने समझाया कि आपको स्पष्ट रूप से कहना है कि आप जेनिक्स में अपनी पुस्तक सी # गहराई में भिन्नता चाहते हैं (बीटीडब्ल्यू, यह एक पढ़ा जाना चाहिए)। संक्षेप में, निष्पादन समय पर टाइप मिस्चैच से बचने के लिए है। आप यह उत्तर भी देख सकते हैं: http://stackoverflow.com/a/246101/574059 और एरिक लिपर्ट द्वारा यह आलेख: https://blogs.msdn.microsoft.com/ericlippert/2007/10/16/covariance-and -contravariance-in-c-part-one/ – gobes

+0

@gobes मुझे पीछे कारण के बारे में पता है।यह ओपी चाहता है कि वापस आ जाता है, उदाहरण के लिए इस मामले में भिन्नता का उपयोग तीसरे पैरामीटर (जावा के समान ही) के मुकाबले कम प्रतिबंधित होगा, कोडर का समाधान मध्य में कहीं है। और लिंक के लिए धन्यवाद। – Theraot

+0

यही वह है! भिन्नता का उपयोग करके, मुझे वह मिला जो मैं शुरुआत में चाहता था: 'क्लास टेक्स्टटास्क: आईटास्क <टेक्स्ट क्वेस्टियन, टेक्स्टएन्सर> '। – Letfar

4

तरह से मैं सवाल समझ में है, तो आप इस प्रकार ITask में एक अतिरिक्त प्रकार पैरामीटर की शुरूआत से बाधा तैयार कर सकते हैं, प्रकार पैरामीटर TQuestion और TAnswer से पहले इस्तेमाल को छोड़ते हुए।

interface ITask<T> 
{ 
    IQuestion<T> Question { get; } 
    List<IAnswer<T>> Answers { get; } 
} 
संबंधित मुद्दे