【问题标题】:Can I retrieve default value of parameter in method?我可以在方法中检索参数的默认值吗?
【发布时间】:2020-03-05 18:46:02
【问题描述】:

例子:

public static double ComputeFoo(double nom, double den, double epsilon = 2.2e-16)
{
    double den1 = den == 0.0 ? epsilon : den;
    // den1 can still be zero if epsilon is zero
    // is there any way to retrieve 2.2e-16 here and assign it to den1?
    return nom/den1;
}

有没有办法检索 2.2e-16 值并在方法中使用它?

P.S.:我知道对于这个特定的示例,我可以致电 ComputeFoo(nom, den1)

【问题讨论】:

  • 2.2e-16 存储为常量,并在默认值和其他任何需要的地方引用它。
  • 如果你真的想获得这个价值,你可以通过反思,但我建议不要做@HereticMonkey已经提到的事情。

标签: c# optional-parameters


【解决方案1】:

您可以在类中的某处设置一个常量值,并将其作为默认值传递给方法。在那里,您可以检查传递的值是否与常量不同,反之亦然:

static void Main(string[] args)
{
     Test(0);
}

const int constantValue = 15;

static int Test(int testValue = constantValue)
{
    Console.WriteLine(testValue);
    Console.WriteLine(constantValue);

    return constantValue;
}

注意:constantValue 必须是常量才能成功构建。

【讨论】:

    【解决方案2】:

    这是我在上面使用Reflection 的评论中提到的另一种方法;通用方法。

    public static T GetDefaultOptionalParamValue<T, TClass>(string methodName, string paramName)
    {
       if (typeof(TClass).GetMethod(methodName)?.GetParameters().Where(p => p.Attributes.HasFlag(ParameterAttributes.Optional) && 
           p.Attributes.HasFlag(ParameterAttributes.HasDefault) && p.Name == paramName)?.FirstOrDefault()?.DefaultValue is T myValue)
       {
          return myValue;
       }
          else { return default; }
    }
    

    你可以这样称呼它:

     var t = GetDefaultOptionalParamValue<double, ClassName>("ComputeFoo", "epsilon");
    

    t 的值为2.2E-16

    【讨论】:

      【解决方案3】:

      System.Diagnostics 中使用反射来访问参数。这将获得封闭函数第三个参数的默认值:

      var x = new StackFrame(0).GetMethod().GetParameters()[2].DefaultValue;
      

      【讨论】:

        【解决方案4】:

        仅从方法中获取默认值是不可能的。这可能对您有用的一种方法是在您的类中将默认值设为常量。例如:

        private const double epsilonDefault = 2.2e-16;
        
        public static double ComputeFoo(double nom, double den, double epsilon = epsilonDefault)
        {
            double den1 = den == 0.0 ? epsilon : den;
            if (den1 == 0) den1 = epsilonDefault;
            return nom / den1;
        }
        

        这样,您的默认值在方法之外声明,并在您需要时可用。

        编辑:为了完整起见,通过反思可以做到这一点,但这对于这个问题来说似乎太多了。一个如何使用反射来做到这一点的基本示例:

        public static void Execute(int number = 10)
        {
            Console.WriteLine(number);
            var defaultValue = typeof(Program)
                    .GetMethod("Execute")
                    .GetParameters()[0]
                    .DefaultValue;
            Console.WriteLine(defaultValue); // 10
        }
        

        【讨论】:

        • 可以通过反射获得该默认值。
        • 对于这项任务,我的反思太多了。遗憾的是我无法更改方法的签名。
        • 嗯,这可能确实有效,但在我看来,这比它的价值更麻烦。这种方式更简单、更干净。
        • @IgorStack 这个方法不会改变方法的签名。只是签名的实现。
        • @Xeno-D 我同意,我只是说,我不同意你的说法。
        【解决方案5】:

        不,你不能。唯一可以设置的默认值是null

        public static double ComputeFoo(double nom, double den, double ?epsilon )
        {
            if (epsilon == null)
                epsilon = 2.2e-16
        
            double den1 = den == 0.0 ? epsilon : den;
            // den1 can still be zero if epsilon is zero
            // is there any way to retrieve 2.2e-16 here and assign it to den1?
            return nom/den1;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-02-25
          • 2010-12-25
          • 1970-01-01
          • 1970-01-01
          • 2011-04-18
          • 2014-04-28
          • 1970-01-01
          • 2017-03-09
          相关资源
          最近更新 更多