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

注意:这个问题在C#还没有支持可选参数(即在C#4之前)时被问到。

我们正在构build一个从C#类以编程方式生成的Web API。 这个类有方法GetFooBar(int a, int b) ,API有一个方法GetFooBar它的查询参数是&a=foo &b=bar

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

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

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

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

另一个select是使用params关键字

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

就像…

 DoSomething(this, that, theOther); 

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

 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 } 

从这个网站:

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

C#允许使用[可选]属性(来自VB,尽pipe在C#中不起作用)。 所以你可以有这样的方法:

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

在我们的API包装中,我们检测可选参数(ParameterInfo p.IsOptional)并设置一个默认值。 我们的目标是将参数标记为可选,而不需要使用参数名称中的“可选”之类的杂项。

你可以使用方法重载…

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

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

你可以使用Nullabletypes…

 GetFooBar(int?a,int?b)

然后可以使用a.HasValue检查是否已经设置了一个参数。

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

 GetFooBar(params object [] args)

如果你想使用命名参数将需要创build一个types来处理它们,但我认为已经有这样的networking应用程序的东西。

你好可选的世界

如果您希望运行时提供默认参数值,则必须使用reflection来进行调用。 没有这个问题的其他build议,但与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 }); } } } 

您可以在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实现了一个名为“命名参数”的function,实际上你可以通过它们的名字传递参数,当然你也可以按你想要的顺序传递参数:)

我同意stephenbayer。 但是由于它是一个web服务,最终用户只需使用一种forms的web方法就比使用同一方法的多个版本更容易。 我认为在这种情况下,可为空的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 } } 

可选参数是方法。 如果你需要一个类的可选参数,你是:

  • 使用c#4.0:在类的构造函数中使用可选的参数,我喜欢的解决scheme,因为它更接近于方法,更容易记住。 这里是一个例子:

     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#版本:您应该使用构造函数链(使用: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 } } 

一个优雅和简单的方法,可以让你省略任何位置的参数,利用可空types如下:

 public void PrintValues(int? a = null, int? b = null, float? c = null, string s = "") { if(a.HasValue) Debug.Log(a); else Debug.Log("-"); if(b.HasValue) Debug.Log(b); else Debug.Log("-"); if(c.HasValue) Debug.Log(c); else Debug.Log("-"); if(s != "") // Different check for strings Debug.Log(s); else Debug.Log("-"); } 

string已经是可空的types,所以他们不需要

一旦你有这个方法,下面的调用都是有效的:

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

当你以这种方式定义一个方法时,你可以自由地通过命名来设置你想要的参数。 有关命名参数和可选参数的更多信息,请参阅以下链接:

命名参数和可选参数(C#编程指南)@ MSDN

在C#中处理这个问题的典型方法就是重载方法。 通过使用不同的参数创build多个版本的方法,您可以有效地创build可选参数。 在参数较less的表单中,您通常会调用方法的forms,并在调用该方法的所有参数中设置默认值。

你可以重载你的方法。 一个方法包含一个参数GetFooBar(int a) ,另一个包含两个参数, GetFooBar(int a, int b)

为什么不从默认的参数中构造一个字典类呢?这个实现和asp.net窗体的查询string几乎一样。

即Request.QueryString [“a”]

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


你也可能想用ASP.NET来查看Web服务 。 Web服务是通过C#类上的属性自动生成的Web API。

我有一个Web服务来写需要7个参数。 每个对由此Web服务包装的sql语句都是一个可选的查询属性。 因此,对非select性参数的两个解决方法浮现在脑海中…都很差:

方法1(param1,param3,param3,param4,param5,param7) )…开始看图片。 这就是疯狂。 方式太多的组合。

现在为一个简单的方式,看起来很尴尬,但应该工作:方法1(param1,布尔useParam1,param2,布尔useParam2等…)

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

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

我不得不在VB.Net 2.0 Web服务中这样做。 我结束了指定参数作为string,然后将其转换为我所需要的。 一个可选参数是用空string指定的。 不是最干净的解决scheme,但它的工作。 只要小心,你可以捕捉到所有可能发生的exception。

如果有人想将callback(或delegate )作为可选parameter passing,可以这样做。

可选的callback参数:

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

晚会有点迟,但我正在寻找这个问题的答案,并最终find了另一种方式来做到这一点。 声明Web方法的可选参数的数据types是XmlNodetypes。 如果省略了可选的arg,那么将被设置为null,如果它存在,则可以通过调用arg.Value来获得string值,即,

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

这种方法还有一个不错的地方,就是为ws生成的.net主页仍然显示参数列表(尽pipe你确实丢失了用于testing的方便的文本input框)。