2009-12-11 12 views
9
public void DoSomething(params object[] args) 
{ 
    // ... 
} 

उपरोक्त हस्ताक्षर के साथ समस्या यह है कि उस विधि को पारित किए जाने वाले प्रत्येक मूल्य-प्रकार को निश्चित रूप से बॉक्स किया जाएगा, और यह मेरे लिए गंभीर प्रदर्शन मुद्दा है।मुक्केबाजी के बिना मूल्य-प्रकार के तर्कों की परिवर्तनीय संख्या?

क्या ऐसी विधि को रद्द करने का कोई तरीका है जो मुक्केबाजी के बिना मूल्य-प्रकारों के परिवर्तनीय संख्या को स्वीकार करता है?

धन्यवाद।

उत्तर

12

आप जेनरिक का उपयोग कर सकते हैं:

public void DoSomething<T>(params T[] args) 
{ 
} 

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


संपादित करें: यदि आपको एक से अधिक प्रकार के पैरामीटर की आवश्यकता है, तो आप कुछ डिग्री के लिए इसे पूरा करने के लिए ओवरलोड का उपयोग कर सकते हैं।

public void DoSomething<T,U>(T arg1, params U[] args) {} 
public void DoSomething<T,U>(T arg1, T arg2, params U[] args) {} 

दुर्भाग्यवश, इसके लिए आपके प्रकार के लिए कई ओवरलोड मौजूद हैं।

वैकल्पिक रूप से, आप सरणियों में सीधे दे सकते हैं:

public void DoSomething<T,U>(T[] args1, U[] args2) {} 

आप अच्छा संकलक वाक्य रचना खो देते हैं, लेकिन फिर तुम दोनों मानकों को पारित कर दिया के किसी भी संख्या हो सकती है।

+0

हाँ, लेकिन यह केवल एक प्रकार के लिए पूरी तर्क सूची के प्रकार को सीमित करता है ... – DxCK

+0

आप ओवरलोड के साथ मिश्रण और मिलान कर सकते हैं ... –

+0

मैंने यहां अधिक जानकारी जोड़ने के लिए संपादित किया है ... –

3

वर्तमान में नहीं, और मैंने जारी की गई .NET 4 जानकारी में इस मुद्दे को संबोधित करने में कुछ भी नहीं देखा है।

यदि यह आपके लिए एक बड़ी प्रदर्शन समस्या है, तो आप आमतौर पर देखे गए पैरामीटर सूचियों के कई अधिभारों पर विचार कर सकते हैं।

मुझे आश्चर्य है, हालांकि: क्या यह वास्तव में एक प्रदर्शन समस्या है, या आप समय-समय पर अनुकूलन कर रहे हैं?

-1

सी # 4.0 में आप नाम (और इस प्रकार वैकल्पिक) पैरामीटर का उपयोग कर सकते हैं! this blog post

+1

ओएमजी ... यह पूरी तरह से अलग विषय है। –

+0

हमम ...मुझे अभी तक यकीन नहीं है कि आवश्यक कार्यक्षमता क्या है इसलिए शायद मैं गलत हूं और शायद मैं नहीं हूं। वाक्यांश "बॉक्सिंग के बिना मूल्य-प्रकार के तर्कों की परिवर्तनीय संख्या स्वीकार करता है" हालांकि मुझे विश्वास है कि नामित पैरामीटर से संतुष्ट हो सकता है .... –

3

पर अधिक जानकारी दें मान लें कि आप जिस विधि को कॉल कर रहे हैं उसे तर्क प्रकार के बारे में पता है। यदि ऐसा है, तो आप उन्हें .NET 4 से उपयुक्त Tuple प्रकार में पैक कर सकते हैं, और ऑब्जेक्ट के रूप में इस विधि को (उदाहरण के लिए ट्यूपल संदर्भ प्रकार) पास कर सकते हैं (क्योंकि सभी टुपल्स के लिए कोई सामान्य आधार नहीं है)।

यहां मुख्य समस्या यह है कि मुक्केबाजी/अनबॉक्सिंग के बिना इस विधि के अंदर तर्कों को संसाधित करना आसान नहीं है, और संभवतः यहां तक ​​कि प्रतिबिंब के बिना भी। सोचने की कोशिश करें कि निकालने के लिए क्या किया जाना चाहिए, मान लें, मुक्केबाजी के बिना एनएच तर्क। आप समझने के साथ समाप्त हो जाएंगे कि आपको या तो शब्दकोश लुकअप (ओं) से निपटना होगा (या तो नियमित Dictionary<K,V> या internal dictionaries सीएलआर द्वारा उपयोग किया जाना चाहिए), या मुक्केबाजी के साथ। जाहिर है, शब्दकोश लुकअप अधिक महंगा है।

मैं क्योंकि वास्तव में हम बहुत समान समस्या के लिए एक समाधान विकसित इस लिख रहा हूँ: हम मुक्केबाजी के बिना our own Tuples साथ काम करने में सक्षम होना चाहिए - मुख्य रूप से तुलना करने और उन्हें deserialize (tuples को डेटाबेस इंजन हम विकसित द्वारा उपयोग किया जाता है, तो प्रदर्शन किसी भी बुनियादी संचालन के हमारे मामले में वास्तव में आवश्यक है)।

लेकिन:

  • हम बहुत जटिल समाधान के साथ खत्म। एक नज़र डालें उदा। TupleComparer पर।
  • मुक्केबाजी की अनुपस्थिति का प्रभाव वास्तव में उतना अच्छा नहीं है जितना हम उम्मीद करते हैं: प्रत्येक मुक्केबाजी/अनबॉक्सिंग ऑपरेशन को एक सरणी इंडेक्सिंग और कुछ वर्चुअल विधि कॉल द्वारा प्रतिस्थापित किया जाता है, दोनों तरीकों की लागत लगभग समान होती है।

हमारे द्वारा विकसित दृष्टिकोण का एकमात्र लाभ यह है कि हम कचरे से Gen0 "बाढ़" नहीं करते हैं, इसलिए Gen0 संग्रह बहुत अधिक होता है। चूंकि जेन 0 संग्रह लागत "लाइव" ऑब्जेक्ट्स द्वारा आवंटित स्थान के लिए आनुपातिक है और उनकी गिनती के लिए, यह ध्यान देने योग्य लाभ लाता है, अगर अन्य आवंटन एल्गोरिदम के निष्पादन (या बस होता है) के साथ इंटरमीक्स करते हैं तो हम इस तरह से अनुकूलित करने का प्रयास करते हैं।

परिणाम: इस अनुकूलन के बाद हमारे सिंथेटिक परीक्षण 0% से 200-300% प्रदर्शन वृद्धि करने के लिए दिखा रहे थे; दूसरी तरफ, डेटाबेस इंजन के सरल प्रदर्शन परीक्षण ने बहुत कम प्रभावशाली सुधार दिखाया है (लगभग 5-10%)। उपरोक्त परतों पर बहुत समय बर्बाद हो गया था (वहां एक सुंदर जटिल ओआरएम भी है), लेकिन ... इसी तरह की चीजों को लागू करने के बाद आप वास्तव में देखेंगे।

संक्षेप में, मैं आपको कुछ और पर ध्यान केंद्रित करने की सलाह देता हूं। यदि यह पूरी तरह से स्पष्ट होगा कि यह आपके आवेदन में एक प्रमुख प्रदर्शन समस्या है, और इसे हल करने के कोई अन्य अच्छे तरीके नहीं हैं, ठीक है, आगे बढ़ें ... अन्यथा आप समय से पहले अपने ग्राहक से या अपने आप से स्टीलिंग कर रहे हैं अनुकूलन

0

पूरी तरह से सामान्य कार्यान्वयन के लिए, सामान्य कार्यवाही एक धाराप्रवाह पैटर्न का उपयोग करना है। कुछ इस तरह:

public class ClassThatDoes 
{ 
    public ClassThatDoes DoSomething<T>(T arg) where T : struct 
    { 
     // process 

     return this; 
    } 
} 

अब आप फोन:

classThatDoes.DoSomething(1).DoSomething(1m).DoSomething(DateTime.Now)//and so on 

हालांकि कि स्थिर वर्गों के साथ काम नहीं करता है (विस्तार के तरीकों ठीक हैं जब से तुम this लौट सकते हैं)।

आपका प्रश्न मूल रूप से वही है: Can I have a variable number of generic parameters? एक अलग तरीके से पूछा गया।

या params कीवर्ड के साथ आइटम की एक सरणी स्वीकार करते हैं:

public ClassThatDoes DoSomething<T>(params T[] arg) where T : struct 
{ 
    // process 

    return this; 
} 

और कॉल:

classThatDoes.DoSomething(1, 2, 3) 
      .DoSomething(1m, 2m, 3m) 
      .DoSomething(DateTime.Now) //etc 

चाहे सरणी भूमि के ऊपर बनाने मुक्केबाजी भूमि के ऊपर से भी कम है कुछ आप अपने आप को तय करने के लिए होगा।

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