2012-03-12 10 views
9

पास करना मैं एक सामान्य प्रिंट फ़ंक्शन चाहता हूं ... प्रिंटजेनेरिक (टी) ... निम्नलिखित मामले में, मुझे क्या याद आ रही है?सी #: जेनेरिक ऑब्जेक्ट

हमेशा की तरह आपकी मदद/अंतर्दृष्टि की सराहना की है ...

public interface ITest 
{} 

public class MyClass1 : ITest 
{ 
    public string myvar = "hello 1"; 
} 

public class MyClass2 : ITest 
{ 
    public string myvar = "hello 2"; 
} 

class DoSomethingClass 
{ 

    static void Main() 
    { 
     MyClass1 test1 = new MyClass1(); 
     MyClass2 test2 = new MyClass2(); 

     Console.WriteLine(test1.myvar); 
     Console.WriteLine(test2.myvar);    
     Console.WriteLine(test1.GetType()); 

     PrintGeneric(test1); 
     PrintGeneric<test2.GetType()>(test2); 
    } 

    // following doesn't compile 
    public void PrintGeneric<T>(T test) 
    { 
     Console.WriteLine("Generic : " + test.myvar); 
    } 
} 
+1

'var' एक चर नाम नहीं किया जा सकता, क्योंकि यह एक कीवर्ड है। क्या आप अपना वास्तविक कोड दिखा सकते हैं। –

+3

@AshBurlaczenko सही नहीं है। 'var' एक प्रासंगिक कीवर्ड है जो सी # 3.0 में जोड़ा गया है। आप इसे पहचानकर्ता नाम के रूप में उपयोग कर सकते हैं। इसी तरह, आप अधिकतर संदर्भों में पहचानकर्ता नाम के रूप में 'उपज', 'चयन',' से' आदि का उपयोग कर सकते हैं। –

+0

वास्तव में "var" ने कंसोल का उपयोग किये बिना काम किया। राइटलाइन ... लेकिन यह एक कीवर्ड का उपयोग पहचानकर्ता नाम के रूप में करने के लिए मेरा बुरा था ... – user1229895

उत्तर

19

यह संकलित नहीं होता है क्योंकि टी कुछ भी हो सकता है, और सबकुछ myvar फ़ील्ड नहीं होगा।

आप myvar एक संपत्ति कर सकता है ITest पर:

public ITest 
{ 
    string myvar{get;} 
} 

और एक संपत्ति के रूप में कक्षाओं पर इसे लागू:

public class MyClass1 : ITest 
{ 
    public string myvar{ get { return "hello 1"; } } 
} 

और फिर अपने पद्धति पर एक सामान्य बाधा डाल:

public void PrintGeneric<T>(T test) where T : ITest 
{ 
    Console.WriteLine("Generic : " + test.myvar); 
} 

लेकिन उस मामले में ईमानदार होने के लिए आप ju से बेहतर हैं सेंट एक ITest में गुजर:

public void PrintGeneric(ITest test) 
{ 
    Console.WriteLine("Generic : " + test.myvar); 
} 
+0

नहीं है I ITest में एक संपत्ति जोड़ा, लेकिन तो यह मुझे बताता है कि मुझे इसे MyClass1/MyClass2 में कार्यान्वित करने की आवश्यकता है ... जो समझ में आता है, लेकिन फिर मुझे एक त्रुटि मिलती है जिसमें कहा गया है कि इसमें पहले से ही myvar – user1229895

+0

की परिभाषा है, ओह हाँ, आपको फ़ील्ड को गुणों में बदलने की आवश्यकता है कक्षाओं को लागू करना आपको दिखाने के लिए मेरा जवाब अपडेट किया गया। – jonnystoten

+0

मैंने जेनेरिक के लिए मुख्य में प्रिंट जेनेरिक (test2) को आज़माया और 'केवल एक असाइनमेंट, कॉल, वृद्धि, कमीशन के रूप में उपयोग की गई कमी' और प्रिंटजेनेरिक (टेस्ट 1) प्रिंटगनेरिक (टेस्ट 1) के लिए प्रिंट करें। और "गैर-स्थैतिक क्षेत्र के लिए एक ऑब्जेक्ट संदर्भ आवश्यक है" – user1229895

0

public void PrintGeneric<T>(T test) where T: ITest 
{ 
    Console.WriteLine("Generic : " + [email protected]); 
} 

कोशिश के रूप में @Ash Burlaczenko ने कहा है कि आप नहीं कर सकते एक कीवर्ड के बाद एक चर नाम, यदि आप reallllly यह चाहता हूँ कीवर्ड से बचने के लिए @ प्रतीक के साथ उपसर्ग

+1

यह काम नहीं करेगा, 'ITest' के पास' var' नामक सदस्य नहीं है। –

+0

केवल तभी काम करने जा रहा है जब आईटेस्ट संपत्ति की विविधता निर्दिष्ट करता है। मुझे यकीन नहीं है कि यह उदाहरण में करता है। –

+0

हाँ अपने सही इस रूप में अच्छी तरह ITest को –

2

आपकी सामान्य विधि में, T एक प्रकार के लिए केवल प्लेसहोल्डर है। हालांकि, कंपाइलर को कंक्रीट प्रकार (एस) का इस्तेमाल रनटाइम के बारे में कुछ भी नहीं पता है, इसलिए यह नहीं मान सकता कि उनके पास var सदस्य होगा। तब

public void PrintGeneric<T>(T test) where T : ITest 

:

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

2

आप सामान्य प्रकार T बारे में अधिक जानकारी प्रदान करने के लिए होगा। आपके वर्तमान PrintGeneric विधि में, T भी string हो सकता है, जिसमें var सदस्य नहीं है।

आप एक क्षेत्र

public interface ITest 
{ 
    string var { get; } 
} 

के बजाय एक संपत्ति के लिए var बदलने और PrintGeneric विधि के लिए एक बाधा where T: ITest जोड़ सकते हैं।

6

आप चीजों की कम से कम एक जोड़े को छूट रहा है:

  • जब तक आप प्रतिबिंब का उपयोग कर रहे हैं, प्रकार तर्क, संकलन समय पर जाना जाने की जरूरत है ताकि आप उपयोग नहीं कर सकते

    PrintGeneric<test2.GetType()> 
    

    ... हालांकि इस मामले में आप की जरूरत नहीं है करने के लिए वैसे भी

  • PrintGenericT क्षण में बारे में कुछ पता नहीं है, इसलिए संकलक ग

    • T विवश करने के लिए ITest इंटरफ़ेस में एक संपत्ति रखो, और बदल PrintGeneric:

      public void PrintGeneric<T>(T test) where T : ITest 
      { 
          Console.WriteLine("Generic : " + test.PropertyFromInterface); 
      } 
      
    • एक संपत्ति रखो एक सदस्य कहा जाता T

    विकल्प खोजने के an't ITest इंटरफ़ेस में और जेनरिक को पूरी तरह से हटाएं:

    जेनरिक के बजाय
    public void PrintGeneric(ITest test) 
    { 
        Console.WriteLine("Property : " + test.PropertyFromInterface); 
    } 
    
  • उपयोग गतिशील टाइपिंग आप उपयोग कर रहे हैं सी # 4

+1

आपके दूसरे कोड स्निपेट में टाइपो के रूप में किया जा सकता है जॉन? आपने जेनेरिक को हटा दिया लेकिन विधि पर अभी भी है? –

+2

@SteveHaigh: दोह, मुझे एक ही समय में फोन पर टाइप करने और बात करने के लिए यही मिलता है। फिक्स्ड, धन्यवाद। –

+0

पहले विकल्प की कोशिश कर रहा है ... मैं "स्ट्रिंग myvar {get;}" को सबसे तेज़ ... जोड़ता हूं लेकिन MyClass1/MyClass2 इंटरफ़ेस सदस्य 'ITest.myvar' को लागू नहीं करता है ... "स्ट्रिंग myvar" {get;} "MyClass1/MyClass2 परिणामों को संकलित त्रुटि में परिणाम कह रहा है कि यह पहले से परिभाषित है? – user1229895

1

आप इस तरह के रूप में, इंटरफ़ेस में कुछ निर्धारित करने होंगे:

public interface ITest 
{ 
    string Name { get; } 
} 

आपके सी में ITest लागू करें lasses:

public class MyClass1 : ITest 
{ 
    public string Name { get { return "Test1"; } } 
} 

public class MyClass2 : ITest 
{ 
    public string Name { get { return "Test2"; } } 
} 

फिर अपने सामान्य Print समारोह, ITest तक सीमित:

public void Print<T>(T test) where T : ITest 
{ 
} 
+0

प्रश्न पर एश की टिप्पणी पर मेरा जवाब देखें। आप पहचानकर्ता नाम के रूप में 'var' का उपयोग कर सकते हैं, जैसे 'उपज', आदि, हालांकि यह शायद एक अच्छा विचार नहीं है। यह एक प्रासंगिक खोजशब्द है। अपने लिए सत्यापित करने के लिए 'int var;' आज़माएं। –

+0

@MehrdadAfshari, आह .. मुझे इसके बारे में पता नहीं था। खैर, आज मैंने सीखा। लेकिन हाँ, ऐसा कुछ नहीं है जो मैं वास्तव में करता हूं :) –

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