2012-01-23 15 views
6

कुछ कोड के लिए डाली मुद्दे को दोहराने के लिए नहीं होगा:क्यों एक वर्ग एक के साथ एक अमूर्त वर्ग से ली गई है, जहां खंड अपने न्यूनतम सामान्य वर्ग

using System; 

public abstract class Response { } 
public abstract class Request<T> where T : Response { } 
public class LoginResponse : Response { } 
public class LoginRequest : Request<LoginResponse> { } 

public class Program 
{ 
    static void Main(string[] args) 
    { 
     LoginRequest login = new LoginRequest(); 


     /* Error: Cannot implicitly convert type 'LoginRequest' to 'Request' */ 
     Request<Response> castTest = login; 


     /* No Error */ 
     Request<LoginResponse> castTest2 = login; 
    } 
} 

जहां तक ​​मैं बता सकता हूँ LoginRequest वर्ग एक अनुरोध है < प्रतिक्रिया > क्योंकि अनुरोध < टी > से लॉगिन प्राप्त होता है और लॉग इन प्रतिक्रिया प्रतिक्रिया से प्राप्त होती है, तो क्या कोई मुझे इस बारे में बता सकता है कि मुझे संकलक त्रुटि क्यों मिलती है?

ध्यान दें: मैं भी एक स्पष्ट कलाकारों की कोशिश की है

उत्तर

8

आपको त्रुटि मिल रही है क्योंकि Request<Response> और Request<LoginResponse> कॉन्वर्स नहीं हैं।

सिर्फ इसलिए कि Response से LoginResponse inherits मतलब यह नहीं है कि Request<LoginResponse>Request<Response> के रूप में इलाज किया जा सकता ही।

MSDN - Covariance and Contravariance in Generics

+0

धन्यवाद, कॉन्वर्सिस की मेरी समझ थोड़ा पतली है और मुझे और पढ़ने की आवश्यकता है। – Robert

7

क्योंकि आपके सामान्य पैरामीटर परोक्ष अपरिवर्तनीय है - दो प्रकार, Request<LoginResponse> और Request<Response> पूरी तरह से अलग हैं। सी # प्रतिनिधि प्रकार और इंटरफेस में 4.0 में विचरण और यहाँ आप के लिए एक समाधान प्रदान कर सकते हैं:

public interface IResponse<out T> where T : Response {} 

यहाँ हम सामान्य प्रकार TCovariant के रूप में घोषित किया है।

एरिक लिपर्ट ने सी # में भिन्नता के विषय पर many good blog posts लिखा है, मैं अत्यधिक उन्हें पढ़ने की सिफारिश करता हूं।

3

LoginRequestRequest<Response> से निकाले जाते हैं नहीं है, यह Request<LoginResponse> से निकला है: इस लेख पढ़ने दीजिए।

एक सामान्य प्रकार एक बार संकलित हो जाने पर एक प्रकार का होता है। टेम्पलेटेड पैरामीटर पदानुक्रम अप्रासंगिक है।

7

ऐसा इसलिए है क्योंकि सी # जेनेरिक कक्षाएं कॉन्वेंट नहीं हैं। सी # आपको निम्नलिखित करने से रोकने की कोशिश कर रहा है:

Request<Response> castTest = login; 
castTest.Response = someOtherKindOfResponse; 

यह उदाहरण शायद सूचियों के साथ अधिक स्पष्ट है। कल्पना करें कि निम्नलिखित काम करते हैं:

var someStringList = new List<String>(); 
var someObjectList = ((List<Object>)someStringList; // This throws a compile exception, thankfully 
someObjectList.Add(1); // If the above worked, then this would compile, but would throw a runtime exception 
+0

मुझे सूची उदाहरण पसंद है यह समझने में आसान बनाता है। – Robert

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