检查方法内部是否传递了某些可选参数

问题描述 投票:0回答:11

如何检查可选参数是否传递给方法?

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;
}
c# nullable argument-passing optional-parameters
11个回答
19
投票

嗯,争论总是会被通过的。默认参数值只是确保用户在调用函数时不必“显式”指定它们。 当编译器看到这样的调用时:

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 }



8
投票
完全相同

相同: 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 }



4
投票

public void ExampleMethod(int required, string optionalstr, int optionalint) { }

默认值由编译器插入到调用点中。如果你会写的话

ExampleMethod(42);

然后编译器将生成调用

ExampleMethod(42, "default string", 10);

您可以比较 
optionalstr

optionalint
的值是否等于默认值,但您不能真正判断它是由编译器还是由开发人员提供。
    


3
投票

但是,您

可以

重载该函数以采用不同的参数。顺便说一句,这是您在 Java 中可以采用的唯一方法,因此如果您采用它,您将会有很好的伙伴。


3
投票

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



1
投票

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

方法2:

您也可以使用覆盖方法:

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 }



0
投票
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; }



0
投票

您可以使用

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

当传递数据库 id(其中记录包含大于 0 的无符号整数)时,此方法特别有效。因此您知道 0 将始终为 null,并且 id 不能为负数。换句话说,除了默认值(数据类型)之外的所有内容都将被接受为传递的参数。

我个人会使用重载方法,但另一种方法(可能超出了这个问题的范围)是将输入参数放入模型中。然后使用模型力边界(例如 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 } }

这会在行为到达您的方法之前强制行为。

希望这对某人有帮助。

使用可为空是一个很好的解决方案..请参阅下面的示例

0
投票
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); }

您可以使用 

0
投票
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。


-2
投票

定义一个极不可能的值作为参数的默认值。

    如果可选参数是引用类型,例如
  1. String
  2. ,则可以使用
  3. null 作为默认值,前提是这不是参数的预期值。 在过程代码中,将参数与默认值进行比较并采取适当的操作。
  4. https://msdn.microsoft.com/en-us/library/849zff9h(v=vs.100).aspx

© www.soinside.com 2019 - 2024. All rights reserved.