如何检查可选参数是否传递给方法?
public void ExampleMethod(int required, string optionalstr = "default string",
int optionalint = 10)
{
if (optionalint was passed)
return;
}
另一种方法是使用
Nullable<T>.HasValue
(MSDN 定义、MSDN 示例):
int default_optionalint = 0;
public void ExampleMethod(int required, int? optionalint,
string optionalstr = "default string")
{
int _optionalint = optionalint ?? default_optionalint;
}
嗯,争论总是会被通过的。默认参数值只是确保用户在调用函数时不必“显式”指定它们。 当编译器看到这样的调用时:
ExampleMethod(1);
它默默地将其转换为:
ExampleMethod(1, "default string", 10);
因此从技术上来说,确定参数是否在运行时传递是不可能的。您能得到的最接近的是:
if (optionalstr == "default string")
return;
但是如果用户像这样显式调用它,则其行为会相同:
ExampleMethod(1, "default string");
如果您确实希望根据是否提供参数而具有不同的行为,则另一种方法是摆脱默认参数并使用重载,如下所示:
public void ExampleMethod(int required)
{
// optionalstr and optionalint not provided
}
public void ExampleMethod(int required, string optionalstr)
{
// optionalint not provided
}
public void ExampleMethod(int required, string optionalstr, int optionalint)
{
// all parameters provided
}
相同:
ExampleMethod(10);
ExampleMethod(10, "default string");
ExampleMethod(10, "default string", 10);
默认值是由编译器在调用站点执行的。
如果您确实希望这两个调用都有效但可区分,则可以使用重载:
// optionalint removed for simplicity - you'd need four overloads rather than two
public void ExampleMethod(int required)
{
ExampleMethodImpl(required, "default string", false);
}
public void ExampleMethod(int required, string optionalstr)
{
ExampleMethodImpl(required, optionalstr, true);
}
private void ExampleMethodImpl(int required, int optionalstr, bool optionalPassed)
{
// Now optionalPassed will be true when it's been passed by the caller,
// and false when we went via the "int-only" overload
}
public void ExampleMethod(int required, string optionalstr, int optionalint)
{
}
默认值由编译器插入到调用点中。如果你会写的话
ExampleMethod(42);
然后编译器将生成调用
ExampleMethod(42, "default string", 10);
您可以比较
optionalstr
或
optionalint
的值是否等于默认值,但您不能真正判断它是由编译器还是由开发人员提供。但是,您
可以重载该函数以采用不同的参数。顺便说一句,这是您在 Java 中可以采用的唯一方法,因此如果您采用它,您将会有很好的伙伴。
if (optionalstr != null)
{
// do something
}
您还可以重载该方法,让一个方法采用可选参数,另一种方法不采用可选参数。 另外,您可以使不带可选参数的方法将 null 传递给重载方法之一。
public void ExampleMethod(int required)
{
ExampleMethod(required, null, 0);
}
public void ExampleMethod(int required, string optionalstr = "default string",
int optionalint = 10)
{
}
public void ExampleMethod(int required, string optionalstr = "default string",
int optionalint = 10)
{
if (optionalint == 10)
return;
}
或
public void ExampleMethod(int required, string optionalstr = "default string",
int? optionalint)
{
if (required.HasValue==false)
return;
}
您也可以使用覆盖方法:
public void ExampleMethod(int required, string optionalstr = "default string")
{
//When this method called, means optionalint was NOT passed
}
public void ExampleMethod(int required, string optionalstr = "default string",
int optionalint)
{
//When this method called, means optionalint was passed
}
Nullable<T>.HasValue
(
MSDN 定义、MSDN 示例):
int default_optionalint = 0;
public void ExampleMethod(int required, int? optionalint,
string optionalstr = "default string")
{
int _optionalint = optionalint ?? default_optionalint;
}
您可以使用
default(int)
new int()
对于某些情况
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/default-values-table
public void ExampleMethod(int optionalInt = default(int))
{
if (optionalInt == default(int)) //no parameter passed
//do something
else //parameter was passed
return;
}
我个人会使用重载方法,但另一种方法(可能超出了这个问题的范围)是将输入参数放入模型中。然后使用模型力边界(例如 10 是默认参数),这让
模型处理参数,而不是方法
public class Example
{
//...other properties
private int _optionalInt;
public int OptionalInt {
get => _optionalInt;
set {
if (value <= default(int))
throw new ArgumentOutOfRangeException("Value cannot be 0 or less");
else if (value == 10)
throw new ArgumentOutOfRangeException("Value cannot be 10");
else
_initValue = value;
}
}
public Example(int optionalInt)
{
OptionalInt = optionalInt; //validation check in constructor
}
}
希望这对某人有帮助。
使用可为空是一个很好的解决方案..请参阅下面的示例
public static void ExampleMethod(bool? optionalBool = null)
{
Console.WriteLine(optionalBool == null ? "Value not passed" : "Value passed");
}
public static void Main()
{
ExampleMethod();
ExampleMethod(true);
ExampleMethod(false);
}
您可以使用
CallerArgumentExpressionAttribute
例如,如果您有
public static void SomeMethod(int x = 0) {
...
}
要检测调用者是否显式传递了
x
,可以将其更改为
public static void SomeMethod(int x = 0, [CallerArgumentExpression("x")] string xExpr = "") {
...
}
如果调用者未传递 xExpr
,则
xExpr
将是空字符串(
x
的默认值)。当然,这是假设调用者也没有显式传递
xExpr
。
if (xExpr != "") {
// caller did pass x explicitly
}
即使调用者传递了 x
的默认值,例如对于 SomeMethod(0)
,检查
xExpr != ""
也将为 true。