Как вы можете использовать дополнительные параметры в C #? - PullRequest
436 голосов
/ 14 октября 2008

Примечание: Этот вопрос задавался в то время, когда C # еще не поддерживал необязательные параметры (т.е. до C # 4).

Мы создаем веб-API, который программно генерируется из класса C #. У класса есть метод GetFooBar(int a, int b), а у API есть метод GetFooBar, принимающий параметры запроса, такие как &a=foo &b=bar.

Классы должны поддерживать необязательные параметры, которые не поддерживаются в языке C #. Какой лучший подход?

Ответы [ 19 ]

953 голосов
/ 27 июля 2010

Удивлен, никто не упомянул C # 4.0 необязательные параметры, которые работают так:

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

Редактировать: Я знаю, что в то время, когда был задан вопрос, C # 4.0 не существовало. Но этот вопрос по-прежнему занимает № 1 в Google за «необязательные аргументы C #», поэтому я подумал - этот ответ стоит того, чтобы быть здесь. К сожалению.

123 голосов
/ 14 октября 2008

Другой вариант - использовать ключевое слово params

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

Называется как ...

DoSomething(this, that, theOther);
74 голосов
/ 14 октября 2008

В 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
}
43 голосов
/ 14 октября 2008

С этого сайта:

http://www.tek -tips.com / viewthread.cfm? QID = 1500861 & страница = 1

C # допускает использование атрибута [Необязательно] (из VB, хотя и не работает в C #). Таким образом, у вас может быть такой метод:

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

В нашей оболочке API мы определяем необязательные параметры (ParameterInfo p.IsOptional) и устанавливаем значение по умолчанию. Цель состоит в том, чтобы пометить параметры как необязательные, не прибегая к кладбищам, таким как наличие «необязательного» в имени параметра.

25 голосов
/ 14 октября 2008

Вы можете использовать метод перегрузки ...

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

Это зависит от сигнатур метода, в приведенном мной примере пропущен метод «только b», поскольку он будет иметь такую ​​же сигнатуру, что и метод «int a».

Вы можете использовать типы Nullable ...

GetFooBar(int? a, int? b)

Затем вы можете проверить, используя a.HasValue, чтобы увидеть, был ли установлен параметр.

Другим вариантом будет использование параметра 'params'.

GetFooBar(params object[] args)

Если вы хотите использовать именованные параметры, потребуется создать тип для их обработки, хотя я думаю, что для веб-приложений уже есть нечто подобное.

22 голосов
/ 22 февраля 2011

Вы можете использовать дополнительные параметры в 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 реализует функцию, называемую «именованные параметры», вы можете передавать параметры по их именам, и, конечно, вы можете передавать параметры в любом порядке :)

19 голосов
/ 14 октября 2008

Hello Optional World

Если вы хотите, чтобы среда выполнения предоставляла значение параметра по умолчанию, вы должны использовать отражение, чтобы сделать вызов. Не так хорошо, как другие предложения по этому вопросу, но совместимо с 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 });
        }
    }
}
14 голосов
/ 23 апреля 2015

Простой способ, который позволяет опустить любые параметры в любую позицию , использует следующие преимущества: обнуляемые типы :

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

8 голосов
/ 14 октября 2008

Я согласен со Стивенбайером. Но поскольку это веб-сервис, конечному пользователю проще использовать только одну форму веб-метода, чем использовать несколько версий одного и того же метода. Я думаю, что в этой ситуации Nullable Types идеально подходят для необязательных параметров.

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
  }  
}
7 голосов
/ 23 мая 2011

необязательные параметры для методов. если вам нужны необязательные аргументы для класса, и вы:

  • использование 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 # до c # 4.0: вы должны использовать цепочку конструктора (используя ключевое слово: this), где более простые конструкторы приводят к «главному конструктору». Пример:

    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
        }
    }
    
...