如何在 C# 中使用可选参数?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/199761/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 17:43:58  来源:igfitidea点击:

How can you use optional parameters in C#?

c#optional-parameters

提问by Kalid

Note:This question was asked at a time when C# did not yet support optional parameters (i.e. before C# 4).

注意:这个问题是在 C# 还不支持可选参数的时候提出的(即在 C# 4 之前)。

We're building a web API that's programmatically generated from a C# class. The class has method GetFooBar(int a, int b)and the API has a method GetFooBartaking query params like &a=foo &b=bar.

我们正在构建一个从 C# 类以编程方式生成的 Web API。该类有方法GetFooBar(int a, int b),API 有一个方法GetFooBar接受查询参数,如&a=foo &b=bar.

The classes needs to support optional parameters, which isn't supported in C# the language. What's the best approach?

这些类需要支持可选参数,而 C# 语言不支持这些参数。最好的方法是什么?

采纳答案by Alex

Surprised no one mentioned C# 4.0 optional parameters that work like this:

令人惊讶的是没有人提到 C# 4.0 的可选参数是这样工作的:

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

Edit:I know that at the time the question was asked, C# 4.0 didn't exist. But this question still ranks #1 in Google for "C# optional arguments" so I thought - this answer worth being here. Sorry.

编辑:我知道在提出问题时,C# 4.0 不存在。但是这个问题在谷歌的“C# 可选参数”中仍然排名第一,所以我认为 - 这个答案值得在这里。对不起。

回答by Kalid

From this site:

从这个网站:

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

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

C# does allow the use of the [Optional] attribute (from VB, though not functional in C#). So you can have a method like this:

C# 确实允许使用 [Optional] 属性(来自 VB,但在 C# 中不起作用)。所以你可以有一个这样的方法:

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

In our API wrapper, we detect optional parameters (ParameterInfo p.IsOptional) and set a default value. The goal is to mark parameters as optional without resorting to kludges like having "optional" in the parameter name.

在我们的 API 包装器中,我们检测可选参数 (ParameterInfo p.IsOptional) 并设置默认值。目标是将参数标记为可选的,而不需要像在参数名称中包含“可选”这样的杂乱无章。

回答by stephenbayer

In C#, I would normally use multiple forms of the method:

在 C# 中,我通常会使用多种形式的方法:

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

UPDATE:This mentioned above WAS the way that I did default values with C# 2.0. The projects I'm working on now are using C# 4.0 which now directly supports optional parameters. Here is an example I just used in my own code:

更新:上面提到的是我使用 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
}

回答by Kepboy

You could use method overloading...

您可以使用方法重载...

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

It depends on the method signatures, the example I gave is missing the "int b" only method because it would have the same signature as the "int a" method.

这取决于方法签名,我给出的示例缺少“int b”唯一方法,因为它与“int a”方法具有相同的签名。

You could use Nullable types...

您可以使用 Nullable 类型...

GetFooBar(int? a, int? b)

You could then check, using a.HasValue, to see if a parameter has been set.

然后,您可以使用 a.HasValue 检查是否已设置参数。

Another option would be to use a 'params' parameter.

另一种选择是使用“params”参数。

GetFooBar(params object[] args)

If you wanted to go with named parameters would would need to create a type to handle them, although I think there is already something like this for web apps.

如果您想使用命名参数,则需要创建一个类型来处理它们,尽管我认为 Web 应用程序已经有了类似的东西。

回答by Tim Jarvis

Another option is to use the params keyword

另一种选择是使用 params 关键字

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

Called like...

被称为...

DoSomething(this, that, theOther);

回答by cfbarbero

The typical way this is handled in C# as stephen mentioned is to overload the method. By creating multiple versions of the method with different parameters you effectively create optional parameters. In the forms with fewer parameters you would typically call the form of the method with all of the parameters setting your default values in the call to that method.

正如斯蒂芬提到的那样,在 C# 中处理这种情况的典型方法是重载该方法。通过创建具有不同参数的方法的多个版本,您可以有效地创建可选参数。在参数较少的表单中,您通常会调用该方法的表单,所有参数都会在调用该方法时设置默认值。

回答by Robert Paulson

Instead of default parameters, why not just construct a dictionary class from the querystring passed .. an implementation that is almost identical to the way asp.net forms work with querystrings.

除了默认参数之外,为什么不直接从传递的查询字符串构造一个字典类……一个几乎与 asp.net 表单处理查询字符串的方式相同的实现。

i.e. Request.QueryString["a"]

即 Request.QueryString["a"]

This will decouple the leaf class from the factory / boilerplate code.

这将使叶类与工厂/样板代码分离。



You also might want to check out Web Services with ASP.NET. Web services are a web api generated automatically via attributes on C# classes.

您可能还想查看使用 ASP.NET 的 Web 服务。Web 服务是通过 C# 类上的属性自动生成的 Web api。

回答by Vivek

I agree with stephenbayer. But since it is a webservice, it is easier for end-user to use just one form of the webmethod, than using multiple versions of the same method. I think in this situation Nullable Types are perfect for optional parameters.

我同意斯蒂芬拜尔的观点。但由于它是一个网络服务,最终用户只使用一种形式的网络方法比使用同一方法的多个版本更容易。我认为在这种情况下,可空类型非常适合可选参数。

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

回答by Hugh Allen

Hello Optional World

你好可选世界

If you want the runtime to supply a default parameter value, you have to use reflection to make the call. Not as nice as the other suggestions for this question, but compatible with VB.NET.

如果您希望运行时提供默认参数值,则必须使用反射来进行调用。不像这个问题的其他建议那么好,但与 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 });
        }
    }
}

回答by Ron K

A little late to the party, but I was looking for the answer to this question and ultimately figured out yet another way to do this. Declare the data types for the optional args of your web method to be type XmlNode. If the optional arg is omitted this will be set to null, and if it's present you can get is string value by calling arg.Value, i.e.,

聚会有点晚了,但我一直在寻找这个问题的答案,并最终想出了另一种方法来做到这一点。将 Web 方法的可选参数的数据类型声明为 XmlNode 类型。如果可选 arg 被省略,这将被设置为 null,如果它存在,您可以通过调用 arg.Value 来获取字符串值,即,

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

What's also decent about this approach is the .NET generated home page for the ws still shows the argument list (though you do lose the handy text entry boxes for testing).

这种方法的另一个优点是 .NET 为 ws 生成的主页仍然显示参数列表(尽管您确实丢失了用于测试的方便的文本输入框)。

回答by Spanky

I have a web service to write that takes 7 parameters. Each is an optional query attribute to a sql statement wrapped by this web service. So two workarounds to non-optional params come to mind... both pretty poor:

我有一个需要 7 个参数的 Web 服务。每个都是此 Web 服务包装的 sql 语句的可选查询属性。所以想到了非可选参数的两种解决方法......都非常糟糕:

method1(param1, param2, param 3, param 4, param 5, param 6, param7) method1(param1, param2, param3, param 4, param5, param 6) method 1(param1, param2, param3, param4, param5, param7)... start to see the picture. This way lies madness. Way too many combinations.

方法1(参数1, 参数2, 参数3, 参数4, 参数5, 参数6, 参数7) 方法1(参数1, 参数2, 参数3, 参数4, 参数5, 参数6) 方法1(参数1, 参数2, 参数3, 参数4, 参数5, 参数7) )...开始看图。这种方式是疯狂的。组合太多了。

Now for a simpler way that looks awkward but should work: method1(param1, bool useParam1, param2, bool useParam2, etc...)

现在使用一种看起来很笨拙但应该工作的更简单的方法:method1(param1, bool useParam1, param2, bool useParam2, etc...)

That's one method call, values for all parameters are required, and it will handle each case inside it. It's also clear how to use it from the interface.

这是一个方法调用,所有参数的值都是必需的,它将处理其中的每种情况。从界面上也很清楚如何使用它。

It's a hack, but it will work.

这是一个黑客,但它会起作用。