Params कीवर्ड का उपयोग क्यों करें?


336

मुझे पता है कि यह एक बुनियादी सवाल है, लेकिन मुझे इसका जवाब नहीं मिला।

इसका उपयोग क्यों करें? यदि आप एक फ़ंक्शन या एक विधि लिखते हैं जो इसका उपयोग कर रहा है, जब आप इसे हटाते हैं तो कोड अभी भी पूरी तरह से काम करेगा, इसके बिना 100%। उदाहरण के लिए:

परम के साथ:

static public int addTwoEach(params int[] args)
{
    int sum = 0;
    foreach (var item in args)
        sum += item + 2;
    return sum;
}

परम के बिना:

static public int addTwoEach(int[] args)
{
    int sum = 0;
    foreach (var item in args)
       sum += item + 2;
    return sum;
}

62
विधि का कोड स्वयं अभी भी पूरी तरह से काम करेगा ... कॉलिंग कोड अच्छी तरह से नहीं हो सकता ...
जॉन स्कीट

7
params कुंजी शब्द का अर्थ है ऑप्शनल पैरामीटर जो विधि से पारित किया जा सकता है या नहीं। एक कुंजी के साथ एक सरणी बाहर शब्द का मतलब है आप विधि के लिए सरणी तर्क पास होना चाहिए।
अनिलयना एन्टारिया

पायथन भाषा एक ही अवधारणा को इतने मीठे रूप से लागू करती है *जैसे कि यहाँ उल्लेखित तारांकन चिह्न ( ) उपसर्गों के साथ ।
RBT

जवाबों:


485

साथparams आप इस तरह अपने विधि कॉल कर सकते हैं:

addTwoEach(1, 2, 3, 4, 5);

बिना params, आप नहीं कर सकते।

इसके अतिरिक्त, आप एक सरणी के साथ विधि को दोनों मामलों में एक पैरामीटर के रूप में कह सकते हैं :

addTwoEach(new int[] { 1, 2, 3, 4, 5 });

यही है, paramsआपको विधि को कॉल करते समय एक शॉर्टकट का उपयोग करने की अनुमति देता है।

असंबंधित, आप अपनी विधि को बहुत छोटा कर सकते हैं:

public static int addTwoEach(params int[] args)
{
    return args.Sum() + 2 * args.Length;
}

17
@ केन: आपको System.Linqनामस्थान को आयात करने की आवश्यकता हो सकती है :)
रणहिरु जूडे कोरे

49
या वापसी args.Sum (i => i + 2);
जन्म

2
एक प्रतिनिधि के साथ योग, हालांकि, संकलित कोड की जटिलता को बढ़ाता है, जो संभवतः कम प्रदर्शन कर सकता है। इस विशेष स्थिति में वास्तव में प्रासंगिक नहीं है, क्योंकि यह किसी भी करीबी परिणाम नहीं होगा, लेकिन यह जानने के लायक है कि संकलक वास्तव में सबसे अच्छा विकल्प बनाने के लिए क्या कर रहा है।
एलन क्लार्क कोपलैंड जूनियर

2
तुम भी इस्तेमाल कर सकते हैं return args.Select(x => x + 2).Sum();
bbvg

1
जब आप जोड़ते हैं paramsतो आप अपने कॉलर्स या मेथड रिज़ॉल्यूशन को तोड़े बिना अतिरिक्त पद्धति के तर्कों को जोड़ने से खुद को बंद कर लेते हैं ।
श्री यंग

93

उपयोग paramsकरने से आप फ़ंक्शन को बिना किसी तर्क के कॉल कर सकते हैं। इसके बिना params:

static public int addTwoEach(int[] args)
{
    int sum = 0;

    foreach (var item in args)
    {
        sum += item + 2;
    }

    return sum;
}

addtwoEach(); // throws an error

इसके साथ तुलना करें params:

static public int addTwoEach(params int[] args)
{
    int sum = 0;

    foreach (var item in args)
    {
        sum += item + 2;
    }

    return sum;
}

addtwoEach(); // returns 0

आम तौर पर, आप पैरामेट्स का उपयोग कर सकते हैं जब तर्कों की संख्या 0 से अनंत तक भिन्न हो सकती है, और एक सरणी का उपयोग कर सकते हैं जब तर्कों की संख्या 1 से अनंत तक भिन्न होती है।


13
वास्तव में एक सरणी खाली हो सकती है। new int[0]। उम्मीद है की यह मदद करेगा! :)
vidstige

22

यह आपको अपनी कॉल में कई प्रकार के मापदंडों को अपनी इच्छानुसार जोड़ने की अनुमति देता है।

addTwoEach(10, 2, 4, 6)

जबकि दूसरे रूप के साथ आपको एक सरणी को पैरामीटर के रूप में उपयोग करना होगा

addTwoEach(new int[] {10,2,4,6})

17

paramsकीवर्ड के साथ एक खतरा यह है, अगर कॉल के बाद विधि को कोडित किया गया है,

  1. किसी ने गलती से / जानबूझकर विधि हस्ताक्षर से एक / अधिक आवश्यक पैरामीटर हटा दिया है , और
  2. हस्ताक्षर परिवर्तन से पहले पैरामीटर के तुरंत पहले एक / अधिक आवश्यक पैरामीटर, पैरामीटर के paramsसाथ टाइप-संगत थे params,

उन कॉल्स को पहले से आवश्यक पैरामीटर्स को वैकल्पिक paramsपैरामीटर के रूप में मानने के लिए एक / अधिक एक्सप्रेशन के साथ संकलित करना जारी रहेगा । मैं सिर्फ इस सबसे खराब स्थिति में भाग गया: paramsपैरामीटर प्रकार का था object[]

यह उल्लेखनीय है क्योंकि डेवलपर्स का उपयोग कंपाइलर के साथ उनकी कलाई को थप्पड़ मारने के लिए किया जाता है, बहुत अधिक सामान्य परिदृश्य जहां पैरामीटर सभी आवश्यक पैरामीटर के साथ एक विधि से हटा दिए जाते हैं (क्योंकि # पैरामीटर की उम्मीद थी कि परिवर्तन होगा)।

मेरे लिए, यह शॉर्टकट के लायक नहीं है। (Type)[]बिना paramsओवरराइड की आवश्यकता के बिना पैरामीटर्स के 0 से अनंत के साथ काम करेंगे। सबसे खराब स्थिति यह है कि आपको उन , new (Type) [] {}कॉल में जोड़ना होगा जहां यह लागू नहीं होता है।

Btw, imho, सबसे सुरक्षित (और सबसे पठनीय अभ्यास) निम्नलिखित है:

  1. नामांकित पैरामीटर्स से गुजरें (जो कि अब हम VB; P में कर सकते हैं, उसके बाद C # ~ 2 दशकों में भी कर सकते हैं ) (क्योंकि:

    1.1। यह एकमात्र तरीका है जो पैरामीटर आदेश, संगत-प्रकार और / या गिनती बदलने के बाद पैरामीटर के लिए पारित अनपेक्षित मूल्यों की रोकथाम की गारंटी देता है ,

    1.2। यह पैरामीटर अर्थ बदलने के बाद उन अवसरों को कम कर देता है , क्योंकि नए अर्थ को दर्शाने वाले संभावित नए पहचानकर्ता का नाम उसके पास दिए जा रहे मूल्य के ठीक बगल में है,

    1.3। यह अल्पविराम की गणना करने और कॉल से हस्ताक्षर करने के लिए आगे पीछे कूदने से बचता है यह देखने के लिए कि क्या पैरामीटर के लिए अभिव्यक्ति पारित की जा रही है, और

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

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

(नोट: कारण 1.2। और 1.3। कॉल को पढ़ने और / या बदले जाने का उल्लेख नहीं करने के लिए प्रारंभिक कॉल को कोड करने पर भी आसानी से त्रुटि की संभावना को कम कर सकते हैं।)

तथा

  1. ऐसा एक - PARAMETER - प्रति - बेहतर पठनीयता के लिए लाइन (क्योंकि:

    2.1। यह कम बरबाद है, और

    2.2। यह दाएं और पीछे बाएं स्क्रॉल करने से बचता है (और ऐसा करने के लिए लाइन - लाइन करना, क्योंकि अधिकांश नश्वर कई लाइनों के बाएं हिस्से को नहीं पढ़ सकते हैं, दाएं स्क्रॉल करें और दाहिने हिस्से को पढ़ें)।

    2.3। यह "बेस्ट प्रैक्टिस" के अनुरूप है, जो हम पहले ही असाइनमेंट स्टेटमेंट के लिए विकसित कर चुके हैं, क्योंकि हर पैरामीटर पास किया गया है एसेनिमेंट स्टेटमेंट (एक स्थानीय चर के लिए एक मान या संदर्भ असाइन करना)। बस जो लोग पालन की तरह नवीनतम शैली कोडिंग में "बेस्ट प्रैक्टिस" प्रत्येक पंक्ति में कई असाइनमेंट वक्तव्य कोडिंग का सपना नहीं होगा एक बार नहीं "बेस्ट प्रैक्टिस" होगा, हम शायद नहीं करना चाहिए (और पकड़ता है मेरी "प्रतिभा" के लिए; पी ) पासिंग पैरामीटर्स के दौरान ऐसा करें।

नोट :

  1. चर में जिनके नाम पैरामीटर्स को दर्शाते हैं, पास होने पर मदद नहीं मिलती है:

    1.1। आप साहित्यिक स्थिरांक (यानी एक सरल 0/1, झूठे / सच्चे या अशक्त) में पास हो रहे हैं, यहां तक ​​कि "बेस्ट प्रैक्टिसेज" के लिए आपको नामांकित कॉन्स्टेंट का उपयोग करने की आवश्यकता नहीं हो सकती है और उनके उद्देश्य को आसानी से विधि नाम से नहीं समझा जा सकता ),

    1.2। विधि काफी निचले स्तर पर है / इस तरह के कॉलर की तुलना में अधिक सामान्य है कि आप नहीं चाहेंगे / अपने वैरिएबल्स को पैरामीटर्स (या इसके विपरीत) के समान / या नाम देने में सक्षम हों, या

    1.3। आप की दोबारा आदेश / हस्ताक्षर कि पहले कॉल अभी भी संकलन क्योंकि प्रकार में हो सकता है में पैरामीटर की जगह हो अभी भी संगत होना।

  2. वीएस जैसे ऑटो-रैप फीचर होने से मैं ऊपर दिए गए 8 कारणों में से केवल एक (# 2.2) को समाप्त करता है। वीएस 2015 के रूप में देर से पहले, यह ऑटो-इंडेंट नहीं किया ((?! वास्तव में, एमएस?!) जो कारण # 2.1 की गंभीरता को बढ़ाता है।

VS में एक विकल्प होना चाहिए जो Named Parameters (पाठ्यक्रम की एक पंक्ति; P) के साथ Method Call snippets उत्पन्न करता है और एक संकलक विकल्प जिसे Named Parameters की आवश्यकता होती है (कॉन्सेप्ट में इसी तरह के विकल्प VB में जो btw, आवश्यकता थी, एक बार सोचा था। समान रूप से अपमानजनक के रूप में, लेकिन अब prolly है आवश्यक द्वारा " 'उत्तम आचरण'")। वास्तव में, " मेरे में वापसदिन ";); 1991 में मेरे करियर के महीनों में, इससे पहले कि मैं नामांकित पैरामीटर के साथ एक भाषा का उपयोग कर रहा था (या यहां तक ​​कि देखा था), मेरे पास विरोधी भेड़चाल था /" बस क्यूज़ आप कर सकते हैं, इसका मतलब आपको नहीं करना चाहिए " / आँख बंद करके "भुना हुआ" के सिरों को काटें "पर्याप्त रूप से किसी को भी ऐसा करने के बिना (इन-लाइन टिप्पणियों का उपयोग करके) अनुकरण करने के लिए। नामांकित पैरामीटर (साथ ही साथ अन्य कीमती सिंटैक्स का उपयोग करने के लिए नहीं" "कीमती" को बचाने के लिए) स्रोत कोड कीस्ट्रोक्स) पंच कार्ड युग का एक अवशेष है जब इनमें से अधिकांश सिंटैक्स शुरू हुए। आधुनिक हार्डवेयर और आईडीई के साथ इसके लिए कोई बहाना नहीं है और बहुत अधिक जटिल सॉफ़्टवेयर जहां पठनीयता बहुत अधिक है, बहुत, बहुतज़्यादा ज़रूरी। "कोड पढ़ा लिखा है की तुलना में अधिक बार पढ़ा जाता है"। जब तक आप गैर-ऑटो-अपडेट किए गए कोड को डुप्लिकेट नहीं कर रहे हैं, तब तक सहेजे गए प्रत्येक कीस्ट्रोक की कीमत तब और अधिक हो सकती है, जब कोई व्यक्ति (यहां तक ​​कि खुद) इसे बाद में पढ़ने की कोशिश कर रहा हो।


2
मुझे समझ नहीं आ रहा है। आप क्यों नहीं लागू कर सकते हैं कि कम से कम एक हो? बिना परम के भी आपको पास होने nullया new object[0]तर्क के रूप में रोकने के लिए कुछ नहीं है ।
केसी

यह संभवतः वैकल्पिक से पहले कभी भी आवश्यक पैरामीटर के लिए खतरनाक है (यदि कॉल कोड होने के बाद उन आवश्यक एक या अधिक को हटा दिया जाता है)। यही कारण है कि मैंने वैकल्पिक मापदंडों पर किसी भी डॉक्स में नमूना कोड में वैकल्पिक पैरामीटर से पहले आवश्यक पैरामीटर कभी नहीं देखा है। Btw, imho, सबसे सुरक्षित (और सबसे पठनीय अभ्यास) नामित मापदंडों से गुजरना है (जो अब हम VB में होने के बाद C # ~ 2 दशकों में भी कर सकते हैं )। वीएस में एक विकल्प होना चाहिए जो नामित मापदंडों के साथ विधि कॉल स्निपेट्स उत्पन्न करता है (और प्रति पंक्ति 1 पैरामीटर ऐसा करता है)।
टॉम

मुझे वास्तव में यकीन नहीं है कि आपका क्या मतलब है। एकमात्र तरीका जो आपके पास आवश्यक पैरामीटर हो सकता है और वैकल्पिक रूप से पहले सभी आवश्यक को निर्दिष्ट करना है।
केसी

1
पूर्व। मैं घोषित myMethodकरता हूं void myMethod(int requiredInt, params int[] optionalInts)। मैं / किसी और कोड एक / अधिक कॉल, यानी myMethod(1), myMethod(1, 21), myMethod(1, 21, 22)। मैं बदल myMethodजाता हूं void myMethod(params int[] optionalInts)। वे सभी कॉल अभी भी बिना किसी त्रुटि के संकलित होंगे, हालांकि उनके 1 पैरामीटर ("1" 's) को स्पष्ट रूप से optionalIntsपैरामीटर के 1 तत्व के रूप में पारित करने का इरादा नहीं था ।
टॉम

ओह। ठीक है, ठीक है, उस विशेष मामले में यह बीमार हो सकता है। मुझे नहीं लगता कि इससे बचने के लिए कोई कारण है अगर आपको एक स्ट्रिंग और 0 से-कई-कई ints या जो भी चाहिए।
केसी

10

ओवरलोड विधियों को बनाने की कोई आवश्यकता नहीं है, बस एक एकल विधि का उपयोग करें, जो नीचे दिखाए गए हैं

// Call params method with one to four integer constant parameters.
//
int sum0 = addTwoEach();
int sum1 = addTwoEach(1);
int sum2 = addTwoEach(1, 2);
int sum3 = addTwoEach(3, 3, 3);
int sum4 = addTwoEach(2, 2, 2, 2);

आपके इनपुट के लिए धन्यवाद, लेकिन मुझे नहीं लगता कि इस तरह के ओवरलोड का कोई समाधान होगा क्योंकि paramsहम बिना किसी संग्रह के किसी भी गणना को कवर करने के लिए एक संग्रह प्रकार पास करेंगे।
6

आप कुछ हद तक सही हैं, लेकिन जो इसे शांत करता है वह एक अधिभार है जिसमें कोई इनपुट पैरामीटर नहीं है जैसे int sum1 = addTwoEach ();
electricalbah

5

params आपको एकल तर्क के साथ विधि को कॉल करने की अनुमति देता है।

private static int Foo(params int[] args) {
    int retVal = 0;
    Array.ForEach(args, (i) => retVal += i);
    return retVal;
}

के Foo(1);बजाय यानी Foo(new int[] { 1 });। परिदृश्यों में शॉर्टहैंड के लिए उपयोगी हो सकता है, जहां आपको एक पूरे सरणी के बजाय एक ही मूल्य में पास करने की आवश्यकता हो सकती है। यह अभी भी उसी तरीके से नियंत्रित किया जाता है, लेकिन इस तरह से कॉल करने के लिए कुछ कैंडी देता है।


5

Params कीवर्ड जोड़ने से पता चलता है कि आप उस पद्धति को कॉल करते समय कई मापदंडों को पारित कर सकते हैं जो कि इसका उपयोग किए बिना संभव नहीं है। अधिक विशिष्ट होना:

static public int addTwoEach(params int[] args)
{
    int sum = 0;

    foreach (var item in args)
    {
        sum += item + 2;
    }

    return sum;
}

जब आप उपरोक्त विधि से कॉल करेंगे तो आप इसे निम्न में से किसी भी तरीके से कॉल कर सकते हैं:

  1. addTwoEach()
  2. addTwoEach(1)
  3. addTwoEach(new int[]{ 1, 2, 3, 4 })

लेकिन जब आप params कीवर्ड हटाएंगे तो ऊपर दिए गए तरीकों में से केवल तीसरा तरीका ठीक काम करेगा। 1 और 2 के मामले में आपको एक त्रुटि मिलेगी।


0

एक और महत्वपूर्ण बात पर प्रकाश डाला जाना चाहिए। यह उपयोग करने के लिए बेहतर है paramsक्योंकि यह प्रदर्शन के लिए बेहतर है। जब आप paramsतर्क के साथ एक विधि कहते हैं और इसके पास कुछ भी नहीं है:

public void ExampleMethod(params string[] args)
{
// do some stuff
}

फोन:

ExampleMethod();

फिर .Net फ्रेमवर्क का एक नया संस्करण ऐसा करता है (.Net फ्रेमवर्क 4.6 से):

ExampleMethod(Array.Empty<string>());

इस Array.Emptyऑब्जेक्ट को बाद में फ्रेमवर्क द्वारा पुन: उपयोग किया जा सकता है, इसलिए निरर्थक आवंटन करने की कोई आवश्यकता नहीं है। जब आप इस विधि को इस तरह कहते हैं तो ये आवंटन होंगे:

 ExampleMethod(new string[] {});

0

बेवकूफ लग सकता है, लेकिन परम बहुआयामी सरणी की अनुमति नहीं देता है। जबकि आप एक फ़ंक्शन के लिए एक बहुआयामी सरणी पास कर सकते हैं।


0

एक और उदाहरण

public IEnumerable<string> Tokenize(params string[] words)
{
  ...
}

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