简体   繁体   English

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

[英]Check inside method whether some optional argument was passed

How do I check if an optional argument was passed to a method? 如何检查是否将可选参数传递给方法?

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

    if (optionalint was passed)
       return;
}

Another approach is to use Nullable<T>.HasValue ( MSDN definitions , MSDN examples ): 另一种方法是使用Nullable<T>.HasValueMSDN定义MSDN示例 ):

int default_optionalint = 0;

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

Well, arguments are always passed. 好吧,争论总是通过。 Default parameter values just ensure that the user doesn't have to explicitly specify them when calling the function. 默认参数值只是确保用户在调用函数时不必显式指定它们。

When the compiler sees a call like this: 当编译器看到这样的调用时:

ExampleMethod(1);

It silently converts it to: 它默默地将其转换为:

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

So it's not techically possible to determine if the argument was passed at run-time. 因此,确定参数是否在运行时传递在技术上是不可能的。 The closest you could get is: 你最接近的是:

if (optionalstr == "default string")
   return;

But this would behave identically if the user called it explicitly like this: 但是如果用户明确地这样调用它,则行为相同:

ExampleMethod(1, "default string");

The alternative, if you really want to have different behavior depending on whether or not a parameter is provided, is to get rid of the default parameters and use overloads instead, like this: 另外,如果你真的想根据是否提供参数而有不同的行为,那就是去除默认参数并改用过载,如下所示:

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
}

You can't, basically. 基本上你不能。 The IL generated for these calls is exactly the same: 为这些调用生成的IL 完全相同

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

The defaulting is performed at the call site, by the compiler. 默认是由编译器在调用站点执行的。

If you really want both of those calls to be valid but distinguishable, you can just use overloading: 如果您确实希望这两个调用都有效但可区分,则可以使用重载:

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

You can't do this in C#. 你不能在C#中做到这一点。

However, you could overload the function to take differing arguments. 但是,您可以重载函数以采用不同的参数。 That, by the way, is the only approach you can take in Java so you'd be in good company if you adopt it. 顺便说一下,这是你可以用Java学习的唯一方法,所以如果你采用它,你就会很好地合作。

You can't check that, because method with optional parameters is a regular method with all parameters, including those which have default values. 您无法检查,因为带有可选参数的方法是包含所有参数的常规方法,包括具有默认值的参数。 So, your method will be compiled into: 因此,您的方法将编译为:

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

}

Default values are inserted by compiler in the call point. 编译器在调用点中插入默认值。 If you'll write 如果你写的话

ExampleMethod(42);

Then compiler will generate call 然后编译器将生成调用

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

You can compare if optionalstr or optionalint has value equal to default value, but you can't really say if it was provided by compiler or by developer. 您可以比较optionalstroptionalint是否具有等于默认值的值,但您无法确定它是由编译器还是开发人员提供的。

You can't, so you need to find a different way to check for the "optional" parameter. 你不能,所以你需要找到一种不同的方法来检查“可选”参数。 You can pass in a null if the parameter isn't being used, and then check 如果未使用该参数,则可以传入null,然后检查

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

You can also overload the method, having one taking the optional parameters and one that doesn't take the optional parameters. 您还可以重载该方法,其中一个采用可选参数,另一个采用不采用可选参数。 Also, you can make it so that the method without the optional parameters passes in nulls to one of the overloaded methods. 此外,您可以将其设置为使得没有可选参数的方法将空值传递给其中一个重载方法。

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

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

}

you can not check directly but you can check it by default value. 你不能直接检查,但你可以默认值检查它。 for example: 例如:

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

    if (optionalint == 10)
       return;
}

or 要么

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

    if (required.HasValue==false)
       return;
}

Approach 2: 方法2:

Also you can use override methods: 您也可以使用覆盖方法:

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
}

Another approach is to use Nullable<T>.HasValue ( MSDN definitions , MSDN examples ): 另一种方法是使用Nullable<T>.HasValueMSDN定义MSDN示例 ):

int default_optionalint = 0;

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

Necromancing an old thread, but thought I'd add something. Necromancing一个旧线程,但我想我会添加一些东西。

You can use default(int) or new int() 你可以使用default(int)new int()

For certain cases the default values can be used to check where an argument was passed. 对于某些情况 ,默认值可用于检查参数的传递位置。 This works for multiple datatypes. 这适用于多种数据类型。 https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/default-values-table 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;
}

This works particularly well when passing database ids where records hold unsigned integers greater than 0. So you know 0 will always be null and no ids can be negative. 这在传递数据库ID时特别有效,其中记录包含大于0的无符号整数。因此,您知道0将始终为null,并且没有id可以为负数。 In other words, everything other than default(datatype) will be accepted as a passed parameter. 换句话说,除默认值(数据类型)之外的所有内容都将被接受为传递参数。


I would personally go with overloading methods, but another approach (which is perhaps outside the scope of this question) is to make the input parameters into a model. 我个人会采用重载方法,但另一种方法(可能超出了本问题的范围)是将输入参数转换为模型。 Then use the model force boundaries (like 10 being default parameter), which lets the model deal with the parameter, instead of the method . 然后使用模型力边界(如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
    }
}

This forces behavior before it reaches your method. 这会在行为到达您的方法之前强制执行。

Hope this helps someone. 希望这有助于某人。

Use nullable is a good solution.. see example below 使用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);
}

To determine whether an argument has been passed to an optional parameter 确定参数是否已传递给可选参数

  1. Define an extremely unlikely value as the default for the parameter. 将极不可能的值定义为参数的默认值。
  2. If the optional parameter is a reference type such as a String , you can use null as the default value, provided this is not an expected value for the argument. 如果可选参数是引用类型(如String) ,则可以使用null作为默认值,前提是这不是参数的预期值。
  3. In the procedure code, compare the parameter against the default value and take the appropriate action. 在过程代码中,将参数与默认值进行比较并执行相应的操作。

https://msdn.microsoft.com/en-us/library/849zff9h(v=vs.100).aspx https://msdn.microsoft.com/en-us/library/849zff9h(v=vs.100).aspx

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM