【问题标题】:Optional Parameters and Default Value可选参数和默认值
【发布时间】:2013-10-08 05:13:11
【问题描述】:

我写了一个带有可选参数的方法

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

但我想在执行 ExampleMethod 之前发送正确的值

【问题讨论】:

    标签: c# methods parameters call optional


    【解决方案1】:

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

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

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

    【讨论】:

    • 其实在我的项目中有6-7个可选参数。所以我不能这样使用它
    • @Melih:这是一件大事,应该是个问题。
    • 实际上根据我的问题,我需要知道我是否可以对编译器说“使用方法中指定的任何默认值”
    • 你最上面的代码对我来说是一个很好的例子,所以在这里我可以捕捉到默认值,但有更简单的关键字等价吗?例如,我想对 param
    • @Melih 您可以使用关键字作为标识符,方法是使用@ 对其进行转义。例如@default.
    【解决方案2】:

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

    这是 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
    

    【讨论】:

      【解决方案3】:

      你能上课吗?

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

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

          【解决方案5】:

          您可以创建一个方法,只进行术语检查并将您想要使用的正确值分配给 var。 (反对默认值)。 然后,在检查了 6-7 个变量后,调用该方法并提供这些变量。

          【讨论】:

            【解决方案6】:

            根据您的最后一句话,我假设您希望参数具有您在输入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;
            }
            

            祝你好运!

            【讨论】:

            • 实际上,我不知道“use_your_default_value_as_specified”。在这种情况下,它表示可选参数的默认值。例如,我有 6-7 个 opt 参数,当我调用 ExampleMethod 时,我将发送参数“如果 ... 使用 ...,否则使用您自己的默认值”
            猜你喜欢
            • 2016-08-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-07-04
            • 1970-01-01
            • 2010-11-10
            • 2021-07-05
            • 1970-01-01
            相关资源
            最近更新 更多