【问题标题】:Iterate through method's parameters for validation purposes迭代方法的参数以进行验证
【发布时间】:2010-12-02 23:37:08
【问题描述】:

我一直认为能够做这样的事情会很有用,例如,检查参数是否有空引用并最终抛出异常。
这样可以节省一些输入,并且不会忘记添加检查是否添加了新参数。

【问题讨论】:

    标签: c# .net null


    【解决方案1】:

    可以迭代已为方法声明的参数(通过反射),但我认为无法为特定方法调用检索这些参数的值...

    也许您可以使用Postsharp,并在执行此检查的位置创建一个切面。然后,在编译时,Postsharp 可以在您编写的每个方法中“编织”方面(注入额外的代码)......

    【讨论】:

      【解决方案2】:

      您可以查看The Validation Application Block,它可以被视为自动验证的示例,而The Unity Application Block(尤其是它的拦截功能)在拦截调用和检查参数方面。

      【讨论】:

        【解决方案3】:

        好吧,除非你数数:

        public void Foo(string x, object y, Stream z, int a)
        {
            CheckNotNull(x, y, z);
            ...
        }
        
        public static void CheckNotNull(params object[] values)
        {
            foreach (object x in values)
            {
                if (x == null)
                {
                    throw new ArgumentNullException();
                }
            }
        }
        

        为避免数组创建受到影响,您可以为不同数量的参数设置多个重载:

        public static void CheckNotNull(object x, object y)
        {
            if (x == null || y == null)
            {
                throw new ArgumentNullException();
            }
        }
        
        // etc
        

        另一种方法是使用属性来声明参数不应为空,并获取PostSharp 以生成适当的检查:

        public void Foo([NotNull] string x, [NotNull] object y, 
                        [NotNull] Stream z, int a)
        {
            // PostSharp would inject the code here.
        }
        

        诚然,我可能希望 PostSharp 将其转换为 Code Contracts 调用,但我不知道两者配合得如何。也许有一天我们就能写出类似Spec#的东西:

        public void Foo(string! x, object! y, Stream! z, int a)
        {
            // Compiler would generate Code Contracts calls here
        }
        

        ...但不会在不久的将来:)

        【讨论】:

        • 在你的情况下 CheckNotNull((object[])null) 呢? :-)
        • 认为作者的意思类似于 javascript 的 arguments 关键字。例如。列出 "Foo(string x, object y, Stream z, int a)" 方法中的所有参数,并在不指定每个参数的情况下测试它们是否为 null,但调用一些通用方法,如 "ValidateArgs(Foo.arguments);" .
        • @Dzmitry:嗯,是的 - 你这还没有准备好生产:)
        • 这种方法的问题是,你必须在每个方法中都写'CheckNotNull',这很乏味......
        • @RobSullivan:因为如果它是一个代码契约调用,那么如果静态检查器认为我可能传入一个空参数,它就会警告我。静态检查岩石:)
        【解决方案4】:

        您可以使用params 关键字定义方法参数。这样就可以将可变长度的参数传递给您的方法。然后你可以遍历它们并检查空引用或任何你想要的。

        public void MyMethod(params object[] parameters) {
             foreach (var p in parameters) {
                 ...
             }
        }
        
        // method call:
        this.MyMethod("foo", "bar", 123, null, new MyClass());
        

        然而,在我看来,这不是一个好的做事方式。您将不得不手动控制参数的类型、它们在输入数组中的位置,并且您将无法在 Visual Studio 中为它们使用智能感知。

        【讨论】:

          【解决方案5】:

          您很可能使用 AOP 库(例如 PostSharp)自动检查参数。

          【讨论】:

            【解决方案6】:

            前段时间我也有同样的问题,但出于记录目的想这样做。我从来没有找到一个好的解决方案,但发现这个链接是关于使用基于 AOP 的方法来记录方法进入和退出的。它的要点是需要使用一个可以读取您的类并在运行时注入代码的框架来完成您想要做的事情。听起来并不容易。

            How do I intercept a method call in C#?

            【讨论】:

              【解决方案7】:

              在提供了一个使用 params 关键字的简单方法示例后,RaYell 说:

              不过,在我看来,这不是一件好事 做事的方式。你不得不 手动控制您的类型 参数,它们在 输入数组,你将无法 在 Visual 中为他们使用智能感知 工作室。

              我当然同意声明一个方法需要两个strings,一个int,一个可以为空的object,另一个使用paramsMyClass 对象是个坏主意。但是,有(在我看来)params 关键字的完全有效和适当的应用,即当参数都是相同类型时。例如:

              public T Max<T>(T x, T y) where T : IComparable<T> {
                  return x.CompareTo(y) > 0 ? x : y;
              }
              
              public T Max<T>(params T[] values) where T : IComparable<T> {
                  T maxValue = values[0];
              
                  for (int i = 1; i < values.Length; i++) {
                      maxValue = Max<T>(maxValue, values[i]);
                  }
              
                  return maxValue;
              }
              

              【讨论】:

                【解决方案8】:
                var mandatoryFields = (new object[] { input1, input2 }).Where(v => v == null || v.ToString().Trim() == "");
                

                您将获得空参数列表。

                那么你可以添加

                if(mandatoryFields.ToArray().Count > 0){}
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2021-12-12
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2021-01-18
                  • 2020-12-09
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多