2008-10-05 18 views
13

जब मैं इस एक सामान्य वर्ग जहां this.value है के साथ की कोशिश टी: 'int' के लिए "प्रकार कनवर्ट नहीं कर सकता 'टी':टाइप करना सामान्य मूल्यों (सी #)

if (this.value.GetType() == typeof(int)) 
{ 
    ((int)this.value)++; 
} 
else 
{ 
    throw new InvalidOperationException 
      ("T must be an int to perform this operation"); 
} 

मैं एक संकलन समय त्रुटि मिलती है "

इस पर एक अभिन्न ऑपरेशन करने के लिए मुझे क्या करना चाहिए। जब ​​यह एक int है?

ध्यान दें कि यह केवल एक उदाहरण है। कोड जेनेरिक के साथ रूपांतरण टाइप करता है, और "int" केवल एक प्रकार का उदाहरण है। टी

उत्तर

24

दुर्भाग्य से, विशिष्ट टी कार्यान्वयन के बारे में संकलक को मनाने के लिए बहुत मुश्किल है। एक (बुरा) दृष्टिकोण (इस पर ध्यान दें बॉक्स और Unbox मूल्य-प्रकार होगा) बीच में आपत्ति उठाने कास्ट करने के लिए है:

int i = (int)(object)this.value; 
i++; 
this.value = (T)(object)i; 

बदसूरत, लेकिन यह काम करता है। .NET 3.5 में मेरे पास जेनेरिक अंकगणितीय, here के लिए कुछ बेहतर रैपर हैं। ऑपरेटर वर्ग MiscUtil का हिस्सा है; सरलतम स्तर पर, मुझे लगता है AddAlternative बहुत अच्छी तरह से काम करेगा:

this.value = Operator.AddAlternative(this.value, 1); 

यह अंतर्निहित < टी यह निष्कर्ष निकाल देना चाहिए, स्वचालित रूप से > int, या आप उन्हें अपने आप को जोड़ सकते हैं:

this.value = Operator.AddAlternative<T,int>(this.value, 1); 

लाभ: यह मूल कोड के लिए बेहतर है क्योंकि यह वास्तव में मूल टी के बारे में परवाह नहीं करता है - यह किसी भी प्रकार (यहां तक ​​कि स्वयं का) भी काम करेगा जो "टी + (टी, इंट)" का समर्थन करता है।

मुझे लगता है कि वहाँ भी एक ChangeType वहाँ में कहीं आसपास छिपा ...

[संपादित करें] कोलिन कश्मीर और दूसरों वास्तु प्रभाव के बारे में एक वैध टिप्पणी कर - लेकिन व्यावहारिक जा रहा है कई बार जब टी वास्तव में करता है इससे कोई फर्क नहीं पड़ता ... लेकिन मैं वास्तव में आवश्यक होने तक इस प्रकार की विशेषज्ञता से बचने के लिए सहमत हूं। उस ने कहा (कॉलिन की पोस्ट पर मेरी टिप्पणी के अनुसार), मूल अंकगणित (वृद्धि, इंट 32 डिवीजन, आदि) जैसी चीजों को करने की क्षमता (उदाहरण के लिए) मैट्रिक्स < टी > [टी के लिए दशमलव/फ्लोट/int/double/आदि] अक्सर अत्यधिक मूल्यवान है।

3

सी # का स्टेटिक टाइपिंग आपको ऐसा करने नहीं देगा, लेकिन आप ऑब्जेक्ट को कास्टिंग के साथ इसे मूर्ख बना सकते हैं। मैं ऐसा करने की अनुशंसा नहीं करता, यह शायद वास्तुकला की समस्या दिखाता है, लेकिन वैसे भी:

using System; 

class Foo<T> 
{ 
    public T value; 

    public void Increment() 
    { 
    if (value is int) value = (T)(object)(((int)(object)value)+1); 
    } 
} 

static class Program 
{ 
    static void Main() 
    { 
    Foo<int> x = new Foo<int>(); 
    x.Increment(); 
    x.Increment(); 
     Console.WriteLine(x.value); 
    }  
} 
0

मुझे नहीं लगता कि मैं समझता हूं कि आप क्या कर रहे हैं। यदि आपको कुछ विशिष्ट प्रकार की आवश्यकता है, तो आपको शायद जेनिक्स का उपयोग नहीं करना चाहिए। आप कर सकते हैं, यह मूर्खतापूर्ण लगता है। यह वही करेगा जो आप पूछ रहे हैं, लेकिन मैं इसकी अनुशंसा नहीं करता हूं।

namespace GenericsOne 
{ 
    using System; 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Sample<int> one = new Sample<int>(); 
     one.AddFive(10); 

     // yes, this will fail, it is to show why the approach is generally not a good one. 
     Sample<DateTime> two = new Sample<DateTime>(); 
     two.AddFive(new DateTime()); 
    } 
} 

} 

namespace GenericsOne 
{ 
    using System; 
public class Sample<T> 
{ 
    public int AddFive(T number) 
    { 
     int junk = 0; 

     try 
     { 
      junk = Convert.ToInt32(number); 
     } 
     catch (Exception) 
     { 
      Console.WriteLine("Nope"); 
     } 

     return junk + 5; 
    } 
} 
} 
+0

यह काम नहीं करता है, संकलक यह निर्धारित करने में असमर्थ है कि उपयोग करने के लिए ToInt32 अधिभार। – AnthonyWJones

+0

हां, यह ठीक काम करता है। इसे वीएस में पेस्ट करें और इसे आजमाएं। – user25306

12

मेरी राय में, जेनेरिक क्लास में टाइप-विशिष्ट कोड एक कोड गंध है। मैं इसे refactor कुछ इस तरह प्राप्त करने के लिए होगा:

public class MyClass<T> 
{ 
... 
} 

public class IntClass : MyClass<int> 
{ 
    public void IncrementMe() 
    { 
    this.value++; 
    } 
} 
+2

हो सकता है - लेकिन कुछ मामलों में जेनेरिक गणित कोड में एक साधारण वृद्धि या Int32 divisor बहुत आम है (यानी मैट्रिक्स जैसे कुछ टी जहां फ्लोट/डबल/दशमलव/int/etc है)। लेकिन कई मामलों में, हाँ: कभी-कभी परिपक्व होता है। –

0

यही कारण है कि मैं वास्तव में संख्यात्मक या ऑपरेशन की कमी in C#4 चाहते हैं।

@Marc Gravell का उत्तर इस (+1) के चारों ओर सबसे अच्छा तरीका है, लेकिन यह निराशाजनक है कि यह जेनेरिक के लिए एक मुद्दा है।

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