检查inside方法是否传递了一些可选参数

时间:2014-01-02 16:05:41

标签: c# nullable argument-passing optional-parameters

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

public void ExampleMethod(int required, string optionalstr = "default string",
    int optionalint = 10)
{

    if (optionalint was passed)
       return;
}

另一种方法是使用Nullable<T>.HasValueMSDN definitionsMSDN examples):

int default_optionalint = 0;

public void ExampleMethod(int required, int? optionalint,
                            string optionalstr = "default string")
{
    int _optionalint = optionalint ?? default_optionalint;
}

10 个答案:

答案 0 :(得分:15)

好吧,争论总是通过。默认参数值只是确保用户在调用函数时不必显式地指定它们。

当编译器看到这样的调用时:

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
}

答案 1 :(得分:6)

基本上,你不能。为这些调用生成的IL 完全相同:

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
}

答案 2 :(得分:4)

您无法在C#中执行此操作。

但是,你可以重载函数以获取不同的参数。顺便说一句,那就是你可以用Java中的唯一的方法,所以如果你采用它,你就会很好地合作。

答案 3 :(得分:3)

您无法检查,因为带有可选参数的方法是包含所有参数的常规方法,包括具有默认值的参数。因此,您的方法将编译为:

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

}

编译器在调用点中插入默认值。如果你要写

ExampleMethod(42);

然后编译器将生成调用

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

您可以比较optionalstroptionalint的值是否等于默认值,但您无法确定它是由编译器还是开发人员提供的。

答案 4 :(得分:3)

你不能,所以你需要找到一种不同的方法来检查“可选”参数。如果未使用该参数,则可以传入null,然后检查

if (optionalstr != null)
{
    // do something
}

您还可以重载该方法,其中一个采用可选参数,另一个采用不采用可选参数。此外,您可以将其设置为不带可选参数的方法将空值传递给其中一个重载方法。

public void ExampleMethod(int required)
{
    ExampleMethod(required, null, 0);
}

public void ExampleMethod(int required, string optionalstr = "default string",
int optionalint = 10)
{

}

答案 5 :(得分: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
}

答案 6 :(得分:0)

另一种方法是使用Nullable<T>.HasValueMSDN definitionsMSDN examples):

int default_optionalint = 0;

public void ExampleMethod(int required, int? optionalint,
                            string optionalstr = "default string")
{
    int _optionalint = optionalint ?? default_optionalint;
}

答案 7 :(得分:0)

改善旧线程,但以为我会添加一些内容。

您可以使用default(int)new int()

某些情况下,默认值可用于检查自变量在哪里传递。这适用于多种数据类型。 https://docs.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可以为负。换句话说,除default(datatype)外的所有内容都将被接受为传递的参数。


我个人会使用重载方法,但是另一种方法(也许不在此问题的范围之内)是将输入参数制成模型。然后使用模型力边界(例如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
    }
}

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

希望这对某人有帮助。

答案 8 :(得分:0)

使用nullable是一个很好的解决方案。请参见下面的示例

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

答案 9 :(得分:-1)

确定参数是否已传递给可选参数

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