सी # असीमित सरणी या विधि के साथ एक सरणी या सूची के साथ विधि?


21

मैंने हाल ही में सीखा है कि आप असीमित मापदंडों के साथ कुछ विधि बना सकते हैं, उदाहरण के लिए:

SomeMethod(params int[] numbers);

लेकिन मेरा सवाल यह है कि उसके बीच अंतर क्या है और सिर्फ एक विधि का निर्माण होता है जो एक सूची या एक सरणी प्राप्त करता है?

SomeMethod(int[] numbers);
SomeMethod(List<int> numbers);

शायद इसका प्रदर्शन में कुछ प्रभाव है? मुझे पूरी तरह से समझ में नहीं आया है कि आप किस तरह से असीमित मापदंडों के साथ पसंद करेंगे।

Google पर त्वरित खोज ने मदद नहीं की, मुझे आशा है कि आप मेरी मदद कर सकते हैं।


इसे देखें: stackoverflow.com/questions/434761/…
Mr.AF

नीचे मेरे जवाब के अलावा, एक सरणी होने के लिए तर्क के प्रकार की paramsभी आवश्यकता होती है। यदि आपको किसी सरणी के अलावा किसी संग्रह का उपभोग करने की आवश्यकता है, तो paramsइसके बजाय गैर- तर्क प्रदान करने के लिए अधिक समझदारी हो सकती है ।
अंकलवर्ल्ड

1
@digitlworld: यदि यह विषय आपको रुचिकर लगे, तो चर्चा के लिए github.com/dotnet/csharplang/issues/179 देखें ।
एरिक लिपिपर्ट

के हस्ताक्षर और / या कार्यान्वयन को देखें Console.Write
डीव

जवाबों:


27

उसके बीच क्या अंतर है और सिर्फ एक विधि है जो एक सूची या एक सरणी प्राप्त करती है?

के बीच भिन्नता

void M(params int[] x)

तथा

void N(int[] x)

यह है कि M को इस तरह कहा जा सकता है:

M(1, 2, 3)

या इस तरह:

M(new int[] { 1, 2, 3 });

लेकिन एन को केवल दूसरे तरीके से बुलाया जा सकता है , पहला तरीका नहीं।

शायद इसका प्रदर्शन में कुछ प्रभाव है?

प्रदर्शन का प्रभाव यह है कि आप Mपहले तरीके से कॉल करते हैं या दूसरे तरीके से, किसी भी तरह से आप एक सरणी बना सकते हैं। एक सरणी बनाने का प्रदर्शन प्रभाव पड़ता है क्योंकि इसमें समय और मेमोरी दोनों लगते हैं। याद रखें कि प्रदर्शन प्रभावों को प्रदर्शन लक्ष्यों के खिलाफ मापा जाना चाहिए; यह संभावना नहीं है कि एक अतिरिक्त सरणी बनाने की लागत गेटिंग कारक है जो बाज़ार में सफलता और विफलता के बीच का अंतर है।

मुझे पूरी तरह से समझ में नहीं आया है कि आप किस तरह से असीमित मापदंडों के साथ पसंद करेंगे।

यह विशुद्ध रूप से और पूरी तरह से कोड के लेखक के लिए एक सुविधा है जो विधि को बुला रहा है; यह केवल छोटा है और लिखना आसान है

M(1, 2, 3);

लिखने के बजाय

M(new int[] { 1, 2, 3 });

यह बस फोन करने वाले की ओर से कुछ कीस्ट्रोक्स बचाता है। बस इतना ही।

कुछ सवाल जो आपने नहीं पूछे लेकिन शायद आप इसका जवाब जानना चाहेंगे:

इस सुविधा को क्या कहा जाता है?

वे तरीके जो कॉल करने वाले की ओर से तर्क की एक चर संख्या को पारित करने की अनुमति देते हैं उन्हें वैरेडिक कहा जाता है । Params विधियाँ C # को चर विधियों को कैसे लागू करती हैं।

ओवरलोड रिज़ॉल्यूशन एक वैरेडिक विधि के साथ कैसे काम करता है?

जब ओवरलोड रिज़ॉल्यूशन समस्या का सामना करना पड़ता है, तो C # "सामान्य" और "विस्तारित" दोनों रूपों पर विचार करेगा, और "सामान्य" फ़ॉर्म हमेशा जीतता है यदि दोनों लागू होते हैं। उदाहरण के लिए, इस पर विचार करें:

void P(params object[] x){}

और हमारे पास एक कॉल है

P(null);

दो लागू संभावनाएं हैं। "सामान्य" रूप में, हम Pसरणी के लिए एक अशक्त संदर्भ कहते हैं और पास करते हैं। "विस्तारित" रूप में, हम कॉल करते हैं P(new object[] { null })। इस मामले में, सामान्य रूप जीतता है। यदि हमारे पास कॉल था P(null, null)तो सामान्य रूप अनुचित और विस्तारित रूप डिफ़ॉल्ट रूप से जीतता है।

चुनौती : मान लीजिए कि हमारे पास var s = new[] { "hello" };एक कॉल है P(s);। बताएं कि कॉल साइट पर क्या होता है और क्यों। आप हैरान हो सकते हैं!

चैलेंज : मान लीजिए हम दोनों है void P(object x){}और void P(params object[] x){}। क्या करता P(null)है, और क्यों करता है?

चैलेंज : मान लीजिए हम दोनों है void M(string x){}और void M(params string[] x){}। क्या करता M(null)है, और क्यों करता है? यह पिछले मामले से कैसे भिन्न है?


Ch2: P(null)बनाम P((object)null)बनाम P((object[])null)- मुझे इस अंतर के लिए स्पष्टीकरण कहां मिल सकता है? ऐसा लगता है nullकि कुछ विशेष प्रकार थे , जो ऑब्जेक्ट ( P(null)) के बजाय एरे में परिवर्तित हो जाते हैं , लेकिन स्ट्रिंग को एंगेजिंग ऑफ़ स्ट्रिंग (अस्पष्ट M(null)) में परिवर्तित करते हैं ( ) ... जो बहुत ही अजीब लगता है, यह अपेक्षा करेगा कि दोनों मामलों में अस्पष्ट हो या पिक एकल-arg संस्करण (जो ऐसा नहीं करता है)। लेकिन मुझे लगता है कि यह सी ++ टेम्प्लेट में सार्वभौमिक संदर्भ ( ) की तरह paramsकिसी भी तरह से सामान्य होने के बारे में अधिक है &&, और इस तरह बेहतर मैच (Ch2 में, Ch3 में नहीं)।
फ़िरदा

@ फ़िरदा: आप सी # विनिर्देश में स्पष्टीकरण पा सकते हैं। विचित्रता का कारण है: अशक्त वस्तु, स्ट्रिंग, ऑब्जेक्ट [] और स्ट्रिंग [] के लिए परिवर्तनीय है। तो सवाल फिर अधिभार संकल्प के लिए सामने आया है: कौन सा रूपांतरण सबसे अच्छा है ? इस मामले में नियंत्रण नियम सामान्य से बेहतर है । हम कैसे बताएं कि कौन सा प्रकार अधिक विशिष्ट है? नियम है: सभी जिराफ जानवर हैं लेकिन सभी जानवर जिराफ नहीं हैं, इसलिए, जिराफ जानवर की तुलना में अधिक विशिष्ट है। सभी object[]हैं object, लेकिन सभी नहीं objectहैं object[], इसलिए object[]अधिक विशिष्ट है।
एरिक लिपर्ट

@ फ़िरदा: अब आप जानते हैं कि तार अस्पष्ट क्यों होते हैं। यह सच नहीं है कि "सभी string[]हैं string।" वास्तव में NO string[]हैं stringऔर NO stringहैं string[], इसलिए stringअधिक विशिष्ट या अधिक सामान्य नहीं है string[], और चुनने के लिए कहने पर हमें एक अस्पष्टता त्रुटि मिलती है।
एरिक लिपर्ट

सभी object[]हैं object... object[]अधिक विशिष्ट है इसलिए P(null)अधिक विशिष्ट सरणी, thx के लिए जाता है, यही वह है जो मुझे याद आ रही थी। यहाँ कुछ नियम मिले: docs.microsoft.com/en-us/dotnet/csharp/language-reference/…
firda

5

बस थोड़ा सा प्रोटोटाइप था। जवाब प्रतीत होता है कि paramsएक सरणी में गुजरने के लिए बस सिंटैक्टिक चीनी है। यह वास्तव में आश्चर्य की बात नहीं है। मैंने एक ही विधि के दो संस्करण बनाए, जहां एकमात्र अंतर "परमेस" कीवर्ड है। दोनों के लिए उत्पन्न IL समान था, सिवाय इसके कि संस्करण पर System.ParamArrayAttributeलागू किया गया था params

इसके अलावा, कॉल साइट पर उत्पन्न IL भी मेरे बीच की विधि को मैन्युअल रूप से घोषित करने new int[]और केवल paramsतर्कों का उपयोग करते हुए विधि को कॉल करने के बीच समान था ।

तो, जवाब "सुविधा" प्रतीत होता है। प्रदर्शन में कोई अंतर नहीं दिखाई देता है। आप paramsइसके बजाय एक सरणी के साथ एक फ़ंक्शन भी कह सकते हैं , इसलिए यह बहुत आश्चर्यजनक नहीं है। अगर यह किसी भी संख्या के मापदंडों (जैसे someMethod(1, 2, 3)) के साथ कॉल करने के लिए आपके तरीके के उपभोक्ता के लिए आसान हो जाता है तो यह नीचे आता है, हमेशा एक संग्रह पहले (जैसे someMethod(new List<int>() { 1, 2, 3 } )) बनाने के लिए।


4

असीमित मापदंडों की विशेषता कई परिदृश्यों में निम्नलिखित लाभ प्रदान करती है:

  1. ढीला युग्मन
  2. बढ़ी हुई पुन: प्रयोज्यता
  3. आवेदन के बेहतर समग्र प्रदर्शन

यहां एक उदाहरण है जहां असीमित मापदंडों का विकल्प एक बढ़िया विकल्प है

विचार करें कि ईमेल भेजने के लिए एक एप्लिकेशन का निर्माण किया जाना चाहिए।

ईमेल भेजने वाला फ़ंक्शन 'टू', 'सीसी' और 'बीसीसी' फ़ील्ड के लिए एकल या कई मानों को संभालने में सक्षम होना चाहिए।

यदि सभी प्रकार के क्षेत्रों (या, CC, BCC) के लिए सरणियों या सूचियों के प्रकार तय किए जाते हैं, तो ईमेल भेजने वाले को कॉल करने के लिए कॉलिंग फ़ंक्शन को 3 सरणियों या सूचियों को परिभाषित करने की सभी जटिलता से निपटने के लिए मजबूर किया जाएगा। ।

भले ही कॉलर ईमेल को केवल एक पते पर भेजना चाहता हो, लेकिन ईमेल भेजने वाला फ़ंक्शन कॉल करने वाले को पैरामीटर के रूप में 3 अलग-अलग सरणियों को परिभाषित करने और भेजने के लिए मजबूर करेगा।

यदि ईमेल प्रेषक फ़ंक्शन असीमित पैरामेट्स दृष्टिकोण लेता है, तो कॉलर फ़ंक्शन को सभी जटिलता से निपटने की आवश्यकता नहीं है।

असीमित पैरामीटर दृष्टिकोण, एरे के निर्माण या सूचियों के निर्माण से जहां कहीं भी अनावश्यक हो, बेहतर रनटाइम परफॉमेंस में योगदान देता है।


2

एक से गैर-प्रदर्शन , शैली परिप्रेक्ष्य, paramsकीवर्ड जब आप मापदंडों के वैकल्पिक सूची भेजना चाहते हैं के लिए वास्तव में अच्छा है।

निजी तौर पर, मैं तब उपयोग करूंगा paramsजब मेरा कोड कुछ ऐसा होगा

SomeMethod('Option1', 'Option17');

void SomeMethod(params string[] options)
{
    foreach(var option in options)
    {
        switch(option): ...
    }
}

इसके बारे में अच्छी बात यह है कि मैं इस विधि का उपयोग हर समय एक सरणी या सूची बनाने के बिना सभी जगह कर सकता हूं।

मैं उपयोग करूंगा arrayया listजब मैं जानता हूं कि मैं हमेशा इस फ़ंक्शन को डेटा का एक सेट पास करूंगा जो पहले से ही एक साथ रखा गया है

List<User> users = GetUsersFromDB();
SomeMethod(users);

मैं paramsलचीलेपन का लाभ देखता हूं जो इसे जोड़ता है। यह आपके कोड के लिए एक अपेक्षाकृत मामूली प्रभाव हो सकता है, लेकिन यह अभी भी एक अच्छा उपकरण है।


1

कॉलिंग कन्वेंशन अलग है। उदाहरण के लिए ...

public class Test
{
    public void Method1( params int[] nums )
    {
        nums.ToList().ForEach( n => Console.WriteLine(n) );
    }

    public void Method2( List<int> nums )
    {
        nums.ForEach( n  => Console.WriteLine(n) );
    }   
}

void Main()
{   
    var t = new Test();
    t.Method1( 1, 2, 3, 4 );
    t.Method2( new List<int>() { 1, 2, 3, 4 } );
}

पहले मामले में, आप विधि के अलग-अलग मापदंडों के रूप में कई ints पास कर सकते हैं। दूसरे में, आपको एक सूची को तत्काल भरने और उसे पारित करने की आवश्यकता होगी।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.