是否可以在C#中迭代方法的参数?

我一直在想能够做这样的事情是有用的,例如,检查空引用的参数并最终抛出exception。
这样可以节省一些打字,并且如果添加新参数,也会忘记添加检查。

好吧,除非算上:

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 

另一种方法是使用属性声明参数不应为null,并获取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#-like:

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

……但不是在不久的将来:)

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

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

但在我看来,这并不是一种好的做事方式。 您必须手动控制参数的类型,它们在输入数组中的位置,并且您将无法在Visual Studio中对它们使用intellisense。

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

如何在C#中拦截方法调用?

可以迭代已经为方法声明的参数(通过reflection),但我看不到为特定方法调用检索那些参数的值…

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

您可以查看validation应用程序块 ,它可以作为自动validation和Unity应用程序块 (特别是其拦截function)的示例,用于拦截调用和检查参数。

您可能很可能使用PostSharp等AOP库自动执行参数检查。

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

但在我看来,这并不是一种好的做事方式。 您必须手动控制参数的类型,它们在输入数组中的位置,并且您将无法在Visual Studio中对它们使用intellisense。

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

 public T Max(T x, T y) where T : IComparable { return x.CompareTo(y) > 0 ? x : y; } public T Max(params T[] values) where T : IComparable { T maxValue = values[0]; for (int i = 1; i < values.Length; i++) { maxValue = Max(maxValue, values[i]); } return maxValue; } 
 var mandatoryFields = (new object[] { input1, input2 }).Where(v => v == null || v.ToString().Trim() == ""); 

您将获得null参数列表。

那么你可以添加

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