tags:

views:

450

answers:

7

I've been thinking that it would be useful to be able to do such a thing, for example, to check the parameters for null references and eventually throw an exception.
This would save some typing and also would make it impossible to forget to add a check if a new parameter is added.

A: 

It is possible to iterate over the parameters that have been declared for a method (via reflection), but I see no way to retrieve the value of those parameters for a specific method call ...

Perhaps you could use Postsharp, and create an aspect in where you perform this check. Then, at compile time, Postsharp can 'weave' the aspect (inject additional code) at every method that you 've written ...

Frederik Gheysels
A: 

You can look into The Validation Application Block which can be treated as an example of automated validation and The Unity Application Block (in particular its interception feature) in respect to intercepting calls and inspecting parameters.

Dzmitry Huba
+7  A: 

Well, not unless you count:

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

To avoid the array creation hit, you could have a number of overloads for different numbers of arguments:

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

// etc

An alternative would be to use attributes to declare that parameters shouldn't be null, and get PostSharp to generate the appropriate checks:

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

Admittedly I'd probably want PostSharp to convert it into Code Contracts calls, but I don't know how well the two play together. Maybe one day we'll be able to write the Spec#-like:

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

... but not in the near future :)

Jon Skeet
In your case what about CheckNotNull((object[])null)? :-)
Dzmitry Huba
Think the author meant something like to javascript's arguments keyword. E.g. list all arguments in the "Foo(string x, object y, Stream z, int a)" method and test them for null without specify every one of them, but call to some generic method like "ValidateArgs(Foo.arguments);".
Kamarey
@Dzmitry: Well, yes - you this isn't quite production-ready yet :)
Jon Skeet
Problem with this approach, is that you have to write 'CheckNotNull' in every method, which is quite tedious ...
Frederik Gheysels
@Kamarey: You can't do that, hence the "not unless you count" bit. Still, it's one statement in each case.
Jon Skeet
@Frederik: If you want it to be declarative, you need to use something like the PostSharp route, as we've both mentioned.
Jon Skeet
@Downvoter: Care to comment why?
Jon Skeet
I kid =) I know that you know all of this stuff. By the way I looking forward reading 2nd edition of C# in Depth. I liked the first edition. O, one more thing - what about "dream book"? Is there any movement there?
Dzmitry Huba
Their IQ suffice only for down voting, not comment
Kamarey
"Admittedly I'd probably want PostSharp to convert it into Code Contracts calls"Why? In this simple case wouldn't a if-then-throw do just fine?
RobSullivan
@RobSullivan: Because if it's a Code Contracts call, then the static checker would be able to warn me if it thought I might pass in a null argument. Static checking rocks :)
Jon Skeet
@Jon Skeet: yes, static checking rocks indeed. But in the current Code Contracts release it only works with VSTS, which I can't afford :( Maybe it will be available for everybody in VS2010 with the inclusion of Code Contracts in .NET 4.0?
RobSullivan
@Dzmitry: Re the "dream book" - I'm not really actively doing anything with the idea yet. But I have some interested parties. It may yet happen, in some form or other :)
Jon Skeet
@RobSullivan: Agreed. Have you voted on http://bit.ly/jXPvw yet?
Jon Skeet
I'll make sure to vote, without static analysis Code Contracts mean very little to me. Thanks for the great answer.
RobSullivan
+1  A: 

You can define method parameter with a params keyword. This will make it possible to pass a variable-length number of parameters to your method. You can then iterate over them and check for null references or whatever you want with it.

public void MyMethod(params object[] parameters) {
     foreach (var p in parameters) {
         ...
     }
}

// method call:
this.MyMethod("foo", "bar", 123, null, new MyClass());

In my opinion however, it's not a good way of doing things. You will have to manually control the type of your parameters, their position in the input array and you won't be able to use intellisense for them in Visual Studio.

RaYell
A: 

You could quite probably automate parameter checking with an AOP library such as PostSharp.

Noldorin
A: 

I had the same question some time ago, but wanted to do so for logging purposes. I never found a good solution, but found this link regarding using an AOP based approach for logging method entries and exit. The gist of it is need to use a framework that can read your class and inject code at runtime to do what you you're trying to do. Doesn't sound easy.

http://stackoverflow.com/questions/25803/how-do-i-intercept-a-method-call-in-c

Binz
A: 

After providing a trivial example of a method using the params keyword, RaYell says:

In my opinion however, it's not a good way of doing things. You will have to manually control the type of your parameters, their position in the input array and you won't be able to use intellisense for them in Visual Studio.

I would certainly agree that declaring a method that takes two strings, one int, an object that can be null, and another MyClass object using params is a bad idea. However, there are (in my opinion) perfectly valid and appropriate applications of the params keyword, namely when the parameters are all of the same type. For example:

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