2012-01-13 15 views
7

पर जेनेरिक प्रकार पैरामीटर को बाधित करना संभव है: संक्षेप में: क्या सामान्य पैरामीटर को परिभाषित करना संभव है जहां टाइप पैरामीटर (T) string या int[] पर बाध्य है? छद्म सी # में, मुझे क्या करना चाहते हैं:स्ट्रिंग या ऐरे

public static int MyMethod<T> (T arg1, T arg2) 
    where T : (has an indexer that returns an int) { 
    // stuff with arg1[i], arg2[j], etc... 
} 

ध्यान दें कि सी # में, की वजह से निर्मित string इंडेक्सर int, निम्नलिखित अभिव्यक्ति के char से अंतर्निहित रूपांतरण के साथ (जो एक char रिटर्न)

int someval = source[index]; 
धागा Constrain generic extension method to base types and string मैं मैं सिर्फमें असंबद्ध प्रकार की एक सूची नहीं बना सकते एहसास प्रति

: इसका मतलब है ठीक है कि क्या source एक ही बात एक string या एक int[] हैबाधा खंड। int[] और string दोनों T: IEnumerable<int> का पालन करेंगे, लेकिन IEnumerable<T> को कार्यान्वयनकर्ताओं को इंडेक्सर होने की आवश्यकता नहीं है, जो कि आम तौर पर एक सामान्य विशेषता है जिसे मैं दोनों प्रकार से उपयोग कर रहा हूं।

इसका उद्देश्य यह है कि मैं कुछ अत्यधिक अनुकूलित स्ट्रिंग पार्सिंग और डेमरो-लेवेनशेटिन दूरी एल्गोरिदम के तेज़ कार्यान्वयन जैसे कार्यों का विश्लेषण कर रहा हूं। मैंने पाया है कि पहले मेरे तारों को int के सरणी में परिवर्तित करने से कभी-कभी दोहराए जाने वाले चरित्र-दर-चरित्र प्रसंस्करण (डी-एल एल्गोरिदम के साथ) में तेजी से निष्पादन हो सकता है। यह काफी हद तक इस तथ्य के कारण है कि int मानों की तुलना करना बहुत तेज है जो char मानों की तुलना करता है।

ऑपरेटिव शब्द 'कभी-कभी' होता है। कभी-कभी तारों पर सीधे संचालन करना और पहले कनवर्टिंग की लागत से बचने और int के सरणी में प्रतिलिपि बनाना बहुत तेज़ है। तो अब मेरे पास घोषणाएं हैं जो घोषणाओं को छोड़कर वास्तव में समान हैं।

बेशक मैं dynamic का उपयोग कर सकता हूं, लेकिन रनटाइम जांच से प्रदर्शन दंड पूरी तरह से विधियों के निर्माण में किए गए किसी भी लाभ को नष्ट कर देता है। (मैं परीक्षण किया था)।

+0

में 'टी' को स्थिर रूप से * या तो * एक प्रकार या किसी अन्य के रूप में इलाज करने के लिए यह समझदारी क्या है? बाधाओं का बिंदु आपको 'टी' प्रकार के चर पर काम करने की अनुमति देता है और न्यूनतम स्तर की संगतता की अपेक्षा करता है। दो परस्पर असंगत प्रकारों को रोकना विचित्र है। –

+0

@ किर्क-वोल: जैसा कि मैंने विस्तार से वर्णन किया है, वे मेरे उद्देश्यों के लिए पारस्परिक रूप से असंगत नहीं हैं। इसके विपरीत, वे समान हैं। मैंने उन विधियों का उपयोग और निर्माण किया है जो 100% समान हैं, सिवाय इसके कि एक संस्करण में पैरामीटर को 'स्ट्रिंग' के रूप में घोषित किया गया है और दूसरे संस्करण में 'int [] 'के रूप में घोषित किया गया है। दोनों मामलों में मैं संग्रह के प्रत्येक सदस्य पर एक पूर्णांक के रूप में काम कर रहा हूं। –

+1

नहीं। 'ऑब्जेक्ट' पर ''स्ट्रिंग' और (कोई भी) 'ऐरे' एकजुट हो जाता है, एक स्ट्रिंग * नहीं * एक' char [] 'सी # में है, हालांकि आप एक स्ट्रिंग से' char [] '* बना सकते हैं , लेकिन यह एक * नया * सरणी ऑब्जेक्ट है जिस पर कॉपी की गई सामग्री है। –

उत्तर

4

आप नहीं हो सकता एक बाधा जो कहती है "इस प्रकार के सूचकांक होना चाहिए"।

हालांकि, आपको एक बाधा हो सकती है जो कहती है "इस प्रकार को एक इंटरफेस को कार्यान्वित करना चाहिए जिसमें इंडेक्सर है"। उदाहरण के लिए, ऐसा इंटरफ़ेस IList<char> हो सकता है।

दुर्भाग्य से, stringIList<char> को लागू नहीं करता, इसलिए आप इसके लिए एक छोटा सा आवरण वर्ग लिखने के लिए होगा:

sealed class StringWrapper : IList<char> 
{ 
    public string String { get; private set; } 
    public StringWrapper(string str) { String = str; } 
    public static implicit operator StringWrapper(string str) 
    { 
     return new StringWrapper(str); 
    } 

    public char this[int index] 
    { 
     get { return String[index]; } 
     set { throw new NotSupportedException(); } 
    } 

    // Etc.... need to implement all the IList<char> methods 
    // (just throw NotSupportedException except in the ones that are trivial) 
} 

और फिर आप इस तरह से अपनी प्रणाली की घोषणा कर सकते हैं:

public static TElement MyMethod<TCollection, TElement>(TCollection arg) 
    where TCollection : IList<TElement> 
{ 
    return arg[0]; 
} 

[...] 

MyMethod<StringWrapper, char>("abc")  // returns 'a' 
MyMethod<int[], int>(new[] { 1, 2, 3 }) // returns 1 
+0

यह वास्तव में काम किया था। 'निहित ऑपरेटर' कथन का एक बहुत चालाक उपयोग। मैंने 'IList 'को लागू करने के लिए' स्ट्रिंगवॉपर 'उदाहरण को संशोधित किया,' टी: IList 'पर मेरी विधियों को बाधित किया, और सफलतापूर्वक संकलित दोनों' स्ट्रिंग' और 'int []' तर्कों के साथ विधियों को कॉल किया। दुर्भाग्यवश यह अभी भी बहुत धीमी थी, इसलिए मैं वास्तव में इसका उपयोग नहीं करूँगा। (दोनों गतिशील 'और प्रस्तुत' IList' रैपर संस्करण अलग स्पष्ट 'int [] 'और' string' अधिभार से 2.8x धीमे थे)। –

+0

मुझे आश्चर्य है कि आप कहते हैं कि यह 'गतिशील' जितना धीमा है, लेकिन आपने इसका परीक्षण किया है, इसलिए मैं आपको विश्वास करता हूं। मुझे आशा है कि इसका मतलब है कि गतिशील आश्चर्यजनक रूप से तेज़ है, और इंटरफ़ेस विधि प्रेषण आश्चर्यजनक रूप से धीमा नहीं है। – Timwi

+0

मैंने आज कुछ अलग परीक्षणों के बड़े सेट पर कुछ अलग परीक्षण किए, और मेरे परिणाम बहुत अलग हो गए: जेनेरिक स्पष्ट 'int []' अधिभार से केवल 5% धीमा था; जेनेरिक <स्ट्रिंगवॉपर> एक स्पष्ट 'स्ट्रिंग' अधिभार से केवल 15% धीमा था; जबकि 'गतिशील' स्पष्ट अधिभार की तुलना में लगभग 50% धीमी थी। –

5

नहीं, सी # आपको इस तरह की "समग्र" बाधा बनाने की अनुमति नहीं देता है।

आपके द्वारा दिखाए गए अभिव्यक्ति का मतलब एक ही बात है, लेकिन आप उस तथ्य का उपयोग अपने लाभ के लिए नहीं कर सकते। सी # जेनेरिक सी ++ टेम्पलेट्स को व्यवस्थित रूप से मिलते हैं, लेकिन वे पूरी तरह से अलग तरीके से काम करते हैं, इसलिए तथ्य यह है कि इंडेक्सर एक ही चीज करता है जो अप्रासंगिक होता है।

आप निश्चित रूप से केवल आवश्यक प्रकारों के साथ दो अधिभार बना सकते हैं, लेकिन इसका मतलब कुछ परेशान प्रति & पेस्ट है। पुनरावृत्ति से बचने के लिए इसे सारणित करने के किसी भी प्रयास से आपको खराब प्रदर्शन होगा।

0

आप अपने विधि हस्ताक्षर

public static int MyMethod<T> (T[] arg1, T[] arg2) 

कर सकता है और स्ट्रिंग तर्क पार करने से पहले String.ToCharArray() का उपयोग (या शायद एक अधिभार में, आप अंदाजा हो ...)

+0

इसके साथ एकमात्र मुद्दा यह है कि ओपी "कुछ बेहद अनुकूलित स्ट्रिंग पार्सिंग और कार्यों का विश्लेषण कर रहा है" - यह बिल्कुल तेज़ नहीं होगा। –

+0

अलास, जो स्ट्रिंग इंडेक्सर का उपयोग करने के उद्देश्य को हरा देता है - सामग्री को कॉपी करने के साथ इंडेक्स एक्सेस _without_। अगर मैं किसी सरणी में कनवर्ट करने जा रहा हूं, तो मैं केवल 'int' की सरणी में बदल जाऊंगा, आसानी से एक्सटेंशन विधि के साथ किया जाता है। –

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