如何在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框)。