आप C # में वैकल्पिक मापदंडों का उपयोग कैसे कर सकते हैं?


492

नोट: यह प्रश्न ऐसे समय में पूछा गया था जब C # ने अभी तक वैकल्पिक मापदंडों (यानी C # 4 से पहले) का समर्थन नहीं किया था।

हम एक वेब एपीआई का निर्माण कर रहे हैं जो प्रोग्रामेटिक रूप से सी # क्लास से उत्पन्न होता है। कक्षा में विधि है GetFooBar(int a, int b)और एपीआई में GetFooBarक्वेरी परम की तरह एक विधि है &a=foo &b=bar

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


7
या प्रतीक्षा इकाई C # 4.0 जारी किया गया है। वैकल्पिक मापदंडों का समर्थन किया जाता है।
मीका

जवाबों:


1053

इस तरह काम करने वाले C # 4.0 वैकल्पिक मापदंडों का कोई भी आश्चर्य नहीं करता है:

public void SomeMethod(int a, int b = 0)
{
   //some code
}

संपादित करें: मुझे पता है कि जिस समय सवाल पूछा गया था, उस समय C # 4.0 मौजूद नहीं था। लेकिन यह प्रश्न अभी भी Google में "C # वैकल्पिक तर्कों" के लिए # 1 स्थान पर है, इसलिए मैंने सोचा - यह उत्तर यहाँ होने के लायक है। माफ़ करना।


58
जिस समय यह प्रश्न पूछा गया था, C # 4.0 मौजूद नहीं था।
फॉरेस्ट मार्वेज़

91
हां, यह अनदेखा कर दिया, क्षमा करें। लेकिन यह प्रश्न अभी भी Google में "C # वैकल्पिक तर्कों" के लिए # 1 स्थान पर है, इसलिए - यह उत्तर यहाँ होने के लायक है :)
एलेक्स

45
अद्यतित जानकारी प्रदान करने के लिए आप पर अच्छा है। आदर्श रूप से मूल उत्तरों को C # 4.0 जैसी वर्तमान जानकारी के साथ अद्यतन किया जाएगा। मेरा मानना ​​है कि एसओ लोग मूल रूप से एक विकी मानसिकता को ध्यान में रखते थे, लेकिन हर कोई किसी और के उत्तर को संपादित करने से थोड़ा डरता है।
रोवन

WebServices के साथ मैंने जो कुछ दिलचस्प खोजा है, वह यह है कि (निश्चित रूप से परियोजना में मैं परीक्षण कर रहा हूं) सभी क्वेरिस्ट्रिंग में बूल मान डिफ़ॉल्ट रूप से वैकल्पिक हैं। जाहिर है वे FALSE करने के लिए डिफ़ॉल्ट हैं।
कार्लोस पी

4
यह ध्यान देने योग्य है कि वैकल्पिक मापदंडों को सभी गैर-वैकल्पिक मापदंडों के बाद रखा जाना चाहिए। यानी आप सार्वजनिक शून्य SomeMethod (int ख = 0, पूर्णांक क) नहीं हो सकता है
एंड्रयू Meservy

129

एक अन्य विकल्प परमेस कीवर्ड का उपयोग करना है

public void DoSomething(params object[] theObjects)
{
  foreach(object o in theObjects)
  {
    // Something with the Objects…
  }
}

कहा जाता है ...

DoSomething(this, that, theOther);

57
यह उत्तर 10 लाइनों में
परम

1
धन्यवाद! इसने मुझे एक साधारण (मेरे वर्तमान उपयोग के मामले के लिए) लॉगिंग फ़ंक्शन लिखने के लिए प्रेरित किया: public void log (params object[] args){ StringBuilder sb = new StringBuilder(); for (int i = 0; i < args.Length; i++){ sb.Append("{"); sb.Append(i.ToString()); sb.Append("}"); sb.Append(" "); } String.Format(sb.ToString(),args).Dump(); }नमूना कॉल:log("...Done,",(watch.ElapsedMilliseconds/1000).ToString(),"s");
pfonseca

क्या आप उल्लेख कर सकते हैं, क्या नेट 3.5 इसका समर्थन करता है? आधिकारिक डॉक्स ने उल्लेख नहीं किया है।
T.Todua

@ T.Todua - मैं 100% निश्चित नहीं हूं कि आप यहां क्या पूछ रहे हैं - डॉटनेट फ्रेमवर्क 3.5 में C # v3.0 शामिल है - संस्करण 3.0 ने पैरामस कीवर्ड का समर्थन किया, लेकिन इसमें वैकल्पिक पैरामीटर नहीं थे, जिसे C # v4.0 में पेश किया गया था। , जो डॉटनेट फ्रेमवर्क 4.0
टिम जार्विस

@TimJarvis हाँ, यही मैं पूछ रहा था। tnx
T.Todua

77

C # में, मैं सामान्यतः विधि के कई रूपों का उपयोग करूंगा:

void GetFooBar(int a) { int defaultBValue;  GetFooBar(a, defaultBValue); }
void GetFooBar(int a, int b)
{
 // whatever here
}

अद्यतन: यह ऊपर उल्लेख किया गया था जिस तरह से मैंने C # 2.0 के साथ डिफ़ॉल्ट मान किया था। अब मैं जिन परियोजनाओं पर काम कर रहा हूं, वे C # 4.0 का उपयोग कर रहे हैं जो अब सीधे वैकल्पिक मापदंडों का समर्थन करता है। यहाँ एक उदाहरण है जिसे मैंने सिर्फ अपने कोड में उपयोग किया है:

public EDIDocument ApplyEDIEnvelop(EDIVanInfo sender, 
                                   EDIVanInfo receiver, 
                                   EDIDocumentInfo info,
                                   EDIDocumentType type 
                                     = new EDIDocumentType(EDIDocTypes.X12_814),
                                   bool Production = false)
{
   // My code is here
}

1
मेरा मानना ​​है कि आप डिफॉल्ट मापदंडों में कंस्ट्रक्टरों को नहीं बुला सकते हैं, उन्हें "कंपाइल-टाइम" संगत करने की आवश्यकता है, न कि "रन-टाइम" ... या मैं गलत हूं?
एलेक्स

45

इस साइट से:

http://www.tek-tips.com/viewthread.cfm?qid=1500861&page=1

C # [वैकल्पिक] विशेषता (VB से, हालांकि C # में कार्यात्मक नहीं है) के उपयोग की अनुमति देता है। तो आपके पास इस तरह की विधि हो सकती है:

using System.Runtime.InteropServices;
public void Foo(int a, int b, [Optional] int c)
{
  ...
}

हमारे एपीआई आवरण में, हम वैकल्पिक पैरामीटर (ParameterInfo p.IsOptional) का पता लगाते हैं और एक डिफ़ॉल्ट मान सेट करते हैं। लक्ष्य पैरामीटर नाम में "वैकल्पिक" होने की तरह कीलों का सहारा लिए बिना मापदंडों को वैकल्पिक के रूप में चिह्नित करना है।


4
लेकिन फिर समारोह फू का उपयोग कैसे करें? फू (1,1), फू (1,1, नल) और फू (1,1, मिसिंग.वल्यू) सभी अपवादों को फेंक देंगे
बोलू

2
अजीब बात है, ऊपर दिए गए कुछ उत्तर इससे बेहतर हैं।
मादोट

26

आप विधि अधिभार का उपयोग कर सकते हैं ...

GetFooBar ()
GetFooBar (int)
GetFooBar (int a, int b)

यह विधि हस्ताक्षरों पर निर्भर करता है, मैंने जो उदाहरण दिया है वह "int b" केवल विधि याद कर रहा है क्योंकि इसमें "int" विधि के समान हस्ताक्षर होंगे।

आप अशक्त प्रकारों का उपयोग कर सकते हैं ...

GetFooBar (int? A, int? B)

फिर आप देख सकते हैं। यदि कोई पैरामीटर सेट किया गया है, तो यह देखने के लिए ।HasValue का उपयोग करके।

एक अन्य विकल्प एक 'परम' पैरामीटर का उपयोग करना होगा।

GetFooBar (params ऑब्जेक्ट [] args)

यदि आप नामित मापदंडों के साथ जाना चाहते हैं, तो उन्हें संभालने के लिए एक प्रकार बनाने की आवश्यकता होगी, हालांकि मुझे लगता है कि वेब एप्लिकेशन के लिए पहले से ही ऐसा कुछ है।


24

आप बिना किसी चिंता के C # 4.0 में वैकल्पिक मापदंडों का उपयोग कर सकते हैं। अगर हमारे पास एक तरीका है:

int MyMetod(int param1, int param2, int param3=10, int param4=20){....}

जब आप विधि कहते हैं, तो आप इस तरह से मापदंडों को छोड़ सकते हैं:

int variab = MyMethod(param3:50; param1:10);

C # 4.0 "नामित मापदंडों" नामक एक सुविधा को लागू करता है, आप वास्तव में उनके नामों से पैरामीटर पारित कर सकते हैं, और निश्चित रूप से आप जो भी आदेश चाहते हैं उसमें पैरामीटर पारित कर सकते हैं :)


20

हैलो ऑप्शनल वर्ल्ड

यदि आप एक डिफ़ॉल्ट पैरामीटर मान की आपूर्ति के लिए रनटाइम चाहते हैं, तो आपको कॉल करने के लिए प्रतिबिंब का उपयोग करना होगा। इस प्रश्न के लिए अन्य सुझावों जितना अच्छा नहीं है, लेकिन VB.NET के साथ संगत है।

using System;
using System.Runtime.InteropServices;
using System.Reflection;

namespace ConsoleApplication1
{
    class Class1
    {
        public static void sayHelloTo(
            [Optional,
            DefaultParameterValue("world")] string whom)
        {
            Console.WriteLine("Hello " + whom);
        }

        [STAThread]
        static void Main(string[] args)
        {
            MethodInfo mi = typeof(Class1).GetMethod("sayHelloTo");
            mi.Invoke(null, new Object[] { Missing.Value });
        }
    }
}

16

एक आसान तरीका जो आपको किसी भी स्थिति में किसी भी पैरामीटर को छोड़ने की अनुमति देता है , निम्न प्रकार से अशक्त प्रकारों का लाभ उठा रहा है:

public void PrintValues(int? a = null, int? b = null, float? c = null, string s = "")
{
    if(a.HasValue)
        Console.Write(a);
    else
        Console.Write("-");

    if(b.HasValue)
        Console.Write(b);
    else
        Console.Write("-");

    if(c.HasValue)
        Console.Write(c);
    else
        Console.Write("-");

    if(string.IsNullOrEmpty(s)) // Different check for strings
        Console.Write(s);
    else
        Console.Write("-");
}

तार पहले से ही अशक्त प्रकार के होते हैं इसलिए उन्हें इसकी आवश्यकता नहीं है ?

एक बार जब आपके पास यह तरीका आ जाता है, तो निम्नलिखित कॉल सभी मान्य होती हैं :

PrintValues (1, 2, 2.2f);
PrintValues (1, c: 1.2f);
PrintValues(b:100);
PrintValues (c: 1.2f, s: "hello");
PrintValues();

जब आप एक विधि को परिभाषित करते हैं, जिस तरह से आपको सिर्फ उन मापदंडों को निर्धारित करने की स्वतंत्रता होती है जिन्हें आप उन्हें नाम देकर चाहते हैं। नाम और वैकल्पिक मापदंडों के बारे में अधिक जानकारी के लिए निम्न लिंक देखें:

नामित और वैकल्पिक तर्क (C # प्रोग्रामिंग गाइड) @ MSDN


9

मैं स्टीफनबायर से सहमत हूं। लेकिन चूंकि यह एक webservice है, इसलिए एंड-यूज़र के लिए एक ही विधि के कई संस्करणों का उपयोग करने की तुलना में वेबमिथोड के सिर्फ एक रूप का उपयोग करना आसान है। मुझे लगता है कि इस स्थिति में अशक्त प्रकार वैकल्पिक मापदंडों के लिए एकदम सही हैं।

public void Foo(int a, int b, int? c)
{
  if(c.HasValue)
  {
    // do something with a,b and c
  }
  else
  {
    // do something with a and b only
  }  
}

+1 सलाह का शब्द। इसे एक आदत मत बनाओ क्योंकि यह वास्तव में गड़बड़ हो सकता है।
मिन्ह्रिक्सन

7

वैकल्पिक पैरामीटर विधियों के लिए हैं। यदि आपको किसी वर्ग के लिए वैकल्पिक तर्क चाहिए और आप हैं:

  • c # 4.0 का उपयोग करना: क्लास के कंस्ट्रक्टर में वैकल्पिक तर्कों का उपयोग करें, एक समाधान जो मुझे पसंद है, क्योंकि यह विधियों के साथ किया जाता है, इसलिए याद रखना आसान है। यहाँ एक उदाहरण है:

    class myClass
    {
        public myClass(int myInt = 1, string myString =
                               "wow, this is cool: i can have a default string")
        {
            // do something here if needed
        }
    }
  • c # 4.0 से पहले के c # वर्जन का उपयोग करते हुए: आपको कंस्ट्रक्टर चेनिंग (इस कीवर्ड का उपयोग करके) का उपयोग करना चाहिए, जहां सरल कंस्ट्रक्टर "मास्टर कंस्ट्रक्टर" की ओर ले जाते हैं। उदाहरण:

    class myClass
    {
        public myClass()
        {
        // this is the default constructor
        }
    
        public myClass(int myInt)
            : this(myInt, "whatever")
        {
            // do something here if needed
        }
        public myClass(string myString)
            : this(0, myString)
        {
            // do something here if needed
        }
        public myClass(int myInt, string myString)
        {
            // do something here if needed - this is the master constructor
        }
    }

3

विशिष्ट तरीके से इसे C # में संभाला जाता है क्योंकि स्टीफन का उल्लेख विधि को अधिभार देने के लिए है। विभिन्न मापदंडों के साथ विधि के कई संस्करण बनाकर आप वैकल्पिक रूप से वैकल्पिक पैरामीटर बनाते हैं। कम मापदंडों वाले रूपों में आप आम तौर पर उस पद्धति में कॉल में अपने डिफ़ॉल्ट मान सेट करने वाले सभी मापदंडों के साथ विधि के रूप को कॉल करेंगे।


2

आप अपने तरीके को ओवरलोड कर सकते हैं। एक विधि में एक पैरामीटर होता है GetFooBar(int a)और दूसरे में दोनों पैरामीटर होते हैं,GetFooBar(int a, int b)


2

ओवरलोड का उपयोग करना या C # 4.0 या इसके बाद के संस्करण का उपयोग करना

 private void GetVal(string sName, int sRoll)
 {
   if (sRoll > 0)
   {
    // do some work
   }
 }

 private void GetVal(string sName)
 {
    GetVal("testing", 0);
 }

1

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

उदाहरण (नया शब्दकोश <string, Object> () पारित किया जाएगा यदि कोई वैकल्पिक पैरामीटर वांछित नहीं हैं):

public bool Method(string ParamA, Dictionary<string,Object> AddlParams) {
    if(ParamA == "Alpha" && (AddlParams.ContainsKey("foo") || AddlParams.ContainsKey("bar"))) {
        return true;
    } else {
        return false;
    }
}

0

डिफ़ॉल्ट मापदंडों के बजाय, केवल उत्तीर्ण की गई क्‍यूरिस्‍ट्रींग से डिक्‍शनरी क्‍लास का निर्माण क्‍यों न करें .. एक कार्यान्वयन जो लगभग उसी तरह से होता है जिस तरह से एस्‍पर्ट के रूप में काम करते हैं।

अर्थात अनुरोध।

यह फैक्ट्री / बॉयलरप्लेट कोड से लीफ क्लास को हटा देगा।


आप ASP.NET के साथ वेब सेवाओं की जाँच करना भी चाह सकते हैं । वेब सेवाएँ सी # कक्षाओं पर विशेषताओं के माध्यम से स्वचालित रूप से उत्पन्न एक वेब एपीआई हैं।


0

पार्टी में थोड़ी देर हो गई, लेकिन मैं इस सवाल के जवाब की तलाश में था और आखिरकार ऐसा करने का एक और तरीका निकाला। XmlNode टाइप करने के लिए अपनी वेब विधि के वैकल्पिक args के लिए डेटा प्रकारों की घोषणा करें। यदि वैकल्पिक arg को छोड़ दिया जाता है तो इसे शून्य पर सेट किया जाएगा, और यदि यह मौजूद है तो आप arg.Value, यानी कॉल करके स्ट्रिंग मान प्राप्त कर सकते हैं।

[WebMethod]
public string Foo(string arg1, XmlNode optarg2)
{
    string arg2 = "";
    if (optarg2 != null)
    {
        arg2 = optarg2.Value;
    }
    ... etc
}

इस दृष्टिकोण के बारे में भी सभ्य है। ws के लिए .NET जेनरेट किया गया होम पेज अभी भी तर्क सूची दिखाता है (हालाँकि आप परीक्षण के लिए आसान टेक्स्ट एंट्री बॉक्स खो देते हैं)।


3
क्या यह अशक्त प्रकारों का उपयोग करने से बेहतर है?
किर्क ब्रॉडहर्स्ट

0

मेरे पास लिखने के लिए एक वेब सेवा है जो 7 मापदंडों को लेती है। प्रत्येक इस वेब सेवा द्वारा लिपटे एक sql बयान के लिए एक वैकल्पिक क्वेरी विशेषता है। तो दो वैकल्पिक गैर-वैकल्पिक पैरामेड के लिए दिमाग में आते हैं ... दोनों बहुत गरीब हैं:

method1 (परम 1, परम 2, परम 3, परम 4, परम 5, परम 6, परम 7) पद्धति 1 (परम 1, परम 2, परम 3, परम 4, परम 5, परम 6) विधि 1 (परम १, परम २, परम ३, परम ४, परम ५) ) ... चित्र देखना शुरू करें। इस तरह से पागलपन होता है। बहुत सारे संयोजन।

अब एक सरल तरीके के लिए जो अजीब लग रहा है, लेकिन काम करना चाहिए: method1 (param1, bool useParam1, param2, bool useParam2, etc ...)

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

यह हैक है, लेकिन यह काम करेगा।


2
यही कारण है कि अशक्त पैरामीटर मौजूद हैं।
किर्क ब्रॉडहर्स्ट

0

मुझे यह VB.Net 2.0 वेब सेवा में करना था। मैंने स्ट्रिंग्स के रूप में मापदंडों को निर्दिष्ट करना समाप्त कर दिया, फिर मुझे जो कुछ भी ज़रूरत थी, उन्हें परिवर्तित कर दिया। एक वैकल्पिक पैरामीटर एक खाली स्ट्रिंग के साथ निर्दिष्ट किया गया था। सबसे साफ समाधान नहीं है, लेकिन यह काम किया। बस सावधान रहें कि आप सभी अपवादों को पकड़ सकते हैं जो हो सकते हैं।


0

केवल अगर किसी को delegateवैकल्पिक पैरामीटर के रूप में कॉलबैक (या ) पास करना है, तो इस तरह से कर सकते हैं।

वैकल्पिक कॉलबैक पैरामीटर:

public static bool IsOnlyOneElement(this IList lst, Action callbackOnTrue = (Action)((null)), Action callbackOnFalse = (Action)((null)))
{
    var isOnlyOne = lst.Count == 1;
    if (isOnlyOne && callbackOnTrue != null) callbackOnTrue();
    if (!isOnlyOne && callbackOnFalse != null) callbackOnFalse();
    return isOnlyOne;
}

0

वैकल्पिक पैरामीटर डिफ़ॉल्ट मापदंडों के अलावा कुछ भी नहीं हैं! मेरा सुझाव है कि आप दोनों को डिफ़ॉल्ट पैरामीटर दें। GetFooBar (int a = 0, int b = 0) यदि आपके पास कोई अतिभारित विधि नहीं है, तो परिणामस्वरूप a = 0, b = 0 होगा यदि आप कोई मान पास नहीं करते हैं, यदि आप 1 मान पास करते हैं, तो परिणाम होगा , 0 के लिए पारित मान, और यदि आप 2 मान पास करते हैं तो 1 को a और दूसरे को b को सौंपा जाएगा।

उम्मीद है कि यह आपके सवाल का जवाब देता है।


0

उस स्थिति में जब डिफ़ॉल्ट मान वैकल्पिक पैरामीटर को जोड़ने का तरीका उपलब्ध नहीं है। .NET OptionalAttribute वर्ग - https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.optional श्रद्धांजलि का उपयोग करना है ? दृश्य = netframework-4.8

कोड का उदाहरण नीचे दिया गया है:

namespace OptionalParameterWithOptionalAttribute
{
    class Program
    {
        static void Main(string[] args)
        {
            //Calling the helper method Hello only with required parameters
            Hello("Vardenis", "Pavardenis");
            //Calling the helper method Hello with required and optional parameters
            Hello("Vardenis", "Pavardenis", "Palanga");
        }
        public static void Hello(string firstName, string secondName, 
            [System.Runtime.InteropServices.OptionalAttribute] string  fromCity)
        {
            string result = firstName + " " + secondName;
            if (fromCity != null)
            {
                result += " from " + fromCity;
            }
            Console.WriteLine("Hello " + result);
        }

    }
}

-4

आप इसे
टाइप 1 भी आज़मा सकते हैं
public void YourMethod(int a=0, int b = 0) { //some code }


टाइप 2
public void YourMethod(int? a, int? b) { //some code }

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