可选参数和默认值

本文关键字:默认值 参数 | 更新日期: 2023-09-27 18:33:27

我写了一个接受可选参数的方法

public void ExampleMethod(int maxValue = 20)
{
  ...
}

我将把它用作

int param = GetSomeValue();
ExampleMethod(param < 20 ? param : use_your_default_value_as_specified);

如果小于 20,请使用 param,否则使用您自己的默认值在 ExampleMethod 中实现(在本例中为 20(。我怎样才能告诉编译器"use_your_default_value_as_specified"?

我知道我可以通过以下方式做到这一点

int param = GetSomeValue();
ExampleMethod(param);
public void ExampleMethod(int maxValue)
{
  if(maxValue > 20)
      maxValue = 20;
}

但我想在执行示例方法之前发送正确的值

可选参数和默认值

告诉编译器使用参数的默认值的唯一方法是根本不指定它。

您可以使用一些反射算法在运行时获取值:

public static object DefaultValueForParameter(Type type, string methodName, int parameterNumber)
{
    return type.GetMethod(methodName).GetParameters()[parameterNumber].DefaultValue;
}
ExampleMethod(param < 20 ? param : (int)DefaultValueForParameter(this.GetType(), "ExampleMethod", 0));

但这不是很优雅或高效。

您可以重构ExampleMethod以改用可为空的参数,如下所示:

public void ExampleMethod(int? maxValue = null)
{
    if(maxValue.HasValue)
        maxValue = 20;
}
ExampleMethod(param < 20 ? (int?)param : null);

这样,实际的默认值隐藏在函数中。就其本身而言,我知道这看起来很像您说不想使用的代码,有一个关键的区别。它将可以传入的值的逻辑与默认值应该是什么分开。在您声明不想使用的解决方案中,不可能将 10 用作maxValue,因为它会在您的方法中被覆盖。

您还可以重构它,以便默认值是公开可用的常量,如下所示:

const int DefaultMaxValue = 20;
public void ExampleMethod(int? maxValue = DefaultMaxValue)
{
    maxValue.Dump();
}
ExampleMethod(param < 20 ? param : DefaultMaxValue);

这样,您就可以获得一个默认值的好处,您可以在代码中的多个位置使用该默认值,而不必每次都指定它。


不过,如果您不喜欢上述任何解决方案,则可以坚持使用最简单的方法。我知道这不是你要找的,但我可能会选择这个:

if (param < 20)
    ExampleMethod(param)
else 
    ExampleMethod();

另请注意,如果ExampleMethod返回了 void 以外的内容,您可以这样做:

var result = param < 20 ? ExampleMethod(param) : ExampleMethod();

这有点尴尬,但它确实允许您检索默认参数。一旦你有了价值,你可以把它和我上面的答案结合起来,到达你想去的地方。

这是 LINQPad 格式。

void Main()
{
    Console.WriteLine(AddEm());
    Console.WriteLine("Default for parm1 is " + GetDefaultParm<int>   (GetType().GetMethod("AddEm"), "parm1"));
    Console.WriteLine("Default for parm2 is " + GetDefaultParm<int>(GetType().GetMethod("AddEm"), "parm2"));
    Console.WriteLine("Default for parm3 is " + GetDefaultParm<int>(GetType().GetMethod("AddEm"), "parm3"));
}
private T GetDefaultParm<T>(MethodInfo m, string parmname) {
    var parm = m.GetParameters().Where(p => p.Name == parmname).FirstOrDefault();
    if (parm != null) {
        return (T) parm.DefaultValue;
    } 
    throw new Exception("Parameter not found.");
}   

// Define other methods and classes here
public int AddEm(int parm1 = 10, int parm2 = 20, int parm3 = 30) {
    return parm1 + parm2 + parm3;
}

输出:

60
Default for parm1 is 10
Default for parm2 is 20
Default for parm3 is 30

你能用一个类吗?

// Individual Parameter Values 
class ParameterValueClass { 
   double _Value; 
   double _Max; 
   public double Value { get { return (_Value < _Max) ? _Value : _Max }
                         set  { _Value = value; } } 
   public ParameterValueClass(Max) { _Max = Max; } 
 } 
// Set of Parameter Values 
class ParameterSetClass { 
      public ParameterValueClass Parameter1;
      public ParameterValueClass Parameter2;
      public ParameterValueClass Parameter3;
      public ParameterSetClass () { 
          Parameter1 = new ParameterValueClass(20);
          Parameter2 = new ParameterValueClass(4.22314);
          Parameter3 = new ParameterValueClass(700000);
      }
 } 
void ExampleMethod(ParameterSetClass Parameters) {
    /// Parameter1.Value returns the Value or "Max" value. Could also use a min value. 
  }

您始终可以使用反射。参数集合中的此示例代码包含具有默认值的参数列表。每个参数都具有具有默认值的属性默认值。

private void Calc(int i, int j, int k = 60, int l = 80)
    {
        var parameters =
            System.Reflection.MethodInfo.GetCurrentMethod().GetParameters().Where(param => param.HasDefaultValue);
      //parameters = {k, l}
    }

您可以创建一个方法,该方法仅执行术语检查并将要用于的正确值分配给 var.(针对默认值(。然后,在检查 6-7 个变量后,调用该方法并提供这些变量。

通过您的最后一句话,我假设您希望参数具有输入 ExampleMethod() 时实际将使用的值。您可以尝试的一件事是创建另一个对象或静态方法来为您计算该值。

class Helper {
    public static int MakeParam(int myParam) {
      return myParam < 20 ? myParam : use_your_default_value_as_specified;
    }
}
...
ExampleMethod(Helper.MakeParam(17));

这允许您对方法外部的参数执行任何逻辑。如果需要,您甚至可以拥有一个允许您传入默认值的版本:

class Helper {
    public static int MakeParam(int myParam) {
      return MakeParam(myParam, use_your_default_value_as_specified);
    }
    public static int MakeParam(int myParam, int myDefault) {
      return myParam < 20 ? myParam : myDefault;
    }
}

然后,可以使用命名参数仅为要使用的参数提供值:

void Main()
{
    Console.WriteLine(AddEm(parm3:50)); // = 80
    Console.WriteLine(AddEm(parm2:50)); // = 90
    Console.WriteLine(AddEm());         // = 60)
}
public int AddEm(int parm1 = 10, int parm2 = 20, int parm3 = 30) {
    return parm1 + parm2 + parm3;
}

祝你好运!