8

We use the .NET 2.0 framework with C# 3.0 (I think it's the last version of C# which can run on the 2.0 version of the framework, correct me if I am wrong).

Is there something built into C# which can make this type of parameter validation more convenient?

public ConnectionSettings(string url, string username, string password,
                          bool checkPermissions)
{
    if (username == null) {
        throw new ArgumentNullException("username");
    }

    if (password == null) {
        throw new ArgumentNullException("password");
    }

    if (String.IsNullOrEmpty(url)) {
        throw new ArgumentException("Must not be null or empty, it was " +
            (url == null ? url : "empty"), "url");
    }

    this.url = url;
    this.username = username;
    this.password = password;
    this.checkPermissions = checkPermissions;
}

That sort of parameter validation becomes a common pattern and results in a lot of "almost boilerplate" code to wade through in our public methods.

If there is nothing built in. Are there any great free libraries which we could use?

Daniel Daranas
  • 22,454
  • 9
  • 63
  • 116
Deleted
  • 4,067
  • 6
  • 33
  • 51
  • I think this line need changing to avoid a null reference exception? (url == null ? url : "empty"), "url"); to (url == null ? "null" : "empty"), "url"); – Iain Ward Aug 03 '10 at 12:20
  • You're looking for an Aspect Oriented Programming tool. I know there are some out there, that integrate with Visual Studio and inject code into your assemblies IL at compile time. But I can't seem to get my google working this morning. –  Aug 03 '10 at 12:20
  • You should be able to knock up some convienience methods to provide most of the functionality but I agree, it'd be nice to have some synthetic sugar for this. I'm especially sick of throwing two seperate exceptions for the two cases of string.IsNullOrEmpty – cristobalito Aug 03 '10 at 12:23
  • Don't settle for anything that makes you put the parameter name in a string. It'll get out of sync with the real name eventually, and with lambda expressions the correct name can be automatically determined. – Ben Voigt Aug 03 '10 at 12:26
  • 1
    possible duplicate of [How to avoid argument validation](http://stackoverflow.com/questions/1608714/how-to-avoid-argument-validation) – Ben Voigt Aug 03 '10 at 12:33
  • Come to think of it, what I do now is I have most of my regular validation code in snippets. Crappy solution is crappy. –  Aug 03 '10 at 12:33
  • I don't know of anything built into C# to make this more concise, but tools like Resharper can handle a lot of the grunt work required to create the validation code and its Rename tool will point out and let you automatically update strings that may be linked to the symbol name (including parameter names in exceptions and XML code comment names). – Dan Bryant Aug 03 '10 at 13:35
  • C# has built in expression tree support, which __definitely__ makes this more concise when done properly. For example, http://charlieflowers.wordpress.com/2009/04/01/elegant-appealing-parameter-validation-syntax-in-c-30/ – Ben Voigt Aug 03 '10 at 23:10

8 Answers8

4

I normally create static helper methods...

E.g.

public static void CheckNotNull(object value, string parameterName)
{
   if(value == null) { throw new ArgumentNullException(parameterName); }
}

Means you can condense your code down to something similar to below and just makes it a little tidier.

CheckNotNull(username, "username");
CheckNotNull(password, "password"); 

Or you can wrap it up as an extension method:

public static void CheckNotNull<T>(this T value, string parameterName)
{
   if(value == null) { throw new ArgumentNullException(parameterName); }
}

And use like:

username.CheckNotNull("username");
password.CheckNotNull("password");

And if you're feeling really fancy, you could probably interrogate the parameter names by using reflection. Reflection's kinda slow, so you'd only do this if you were going to throw an exception, but it saves you typing the literal parameter name all the time.

Ian
  • 33,605
  • 26
  • 118
  • 198
  • Still requires putting the parameter name in a string (which you've conveniently left out). – Ben Voigt Aug 03 '10 at 12:28
  • Ben, indeed that was a mistake but fixed before the downvote. – Ian Aug 03 '10 at 12:30
  • Thanks Ben. I've also added a comment about reflection, I'm not sure how to implement it off the top of my head, but should provide a neat solution if it's dooable and solve the whole nasty string problem. – Ian Aug 03 '10 at 12:32
  • You can't, with that syntax. You need an expression tree. For example http://stackoverflow.com/questions/1608714/how-to-avoid-argument-validation – Ben Voigt Aug 03 '10 at 12:35
  • Oops, wrong URL on my clipboard. I meant to link http://charlieflowers.wordpress.com/2009/04/01/elegant-appealing-parameter-validation-syntax-in-c-30/ – Ben Voigt Aug 03 '10 at 23:10
  • I like that link, thanks for that (it's probably something I'll use in my own code). You can get part of the way using Reflection, but I think you might be right, can't quite get all the way. If you get the last frame on the stack you can grab a method info. From that you can get a set of ParameterInfo's which include names. It's just figuring out which one was passed to you :/ – Ian Aug 04 '10 at 08:10
4

You could use an il weaver like Post Sharp, keep in mind that compiler as a service in C# 5 will make this kind of stuff built in.

Personally I would not recommend this approach unless the problem is huge and must be tackled. Usually a few asserts and checking preconditions as you described above is a best practice.

EG:

public ConnectionSettings(
   [NotNullOrEmpty] string url, 
   [NotNull] string username, 
   [NotNull] string password,
   bool checkPermissions)
{
    this.url = url;
    this.username = username;
    this.password = password;
    this.checkPermissions = checkPermissions;
}

You could also integrate this kind of stuff with code contracts which would allow you to perform some rich static analysis.

Sam Saffron
  • 128,308
  • 78
  • 326
  • 506
3

Here's a nice fluent way of doing this.

What are your favorite extension methods for C#? (codeplex.com/extensionoverflow)

public static class Extensions
{
        public static void ThrowIfArgumentIsNull<T>(this T obj, string parameterName) where T : class
        {
                if (obj == null) throw new ArgumentNullException(parameterName + " not allowed to be null");
        }
}

internal class Test
{
        public Test(string input1)
        {
                input1.ThrowIfArgumentIsNull("input1");
        }
}
Community
  • 1
  • 1
this. __curious_geek
  • 42,787
  • 22
  • 113
  • 137
  • Giorgi already mentioned this method. Also... you still have that ugly string with the parameter name in it. – Ben Voigt Aug 03 '10 at 12:29
2

You can do it using contracts but it is the same concept.

This should be good practise anyhow, because it clearly shows what are mandatory fields on a public method.

Datoon
  • 566
  • 5
  • 12
2

It's not build into the .Net Framework but you can use Fluent Argument Validation

Giorgi
  • 30,270
  • 13
  • 89
  • 125
2

Similar idea to fluent parameter validation as mentioned by Giorgi, but this one avoids redundantly naming the parameter, and the strings that can't be automatically updated by code refactoring tools.

http://charlieflowers.wordpress.com/tag/parameter-validation/

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
1

Just to add to Sam's answer above, here's a link which tells you how you can go about implementing such attributes with PostSharp:

http://dpatrickcaldwell.blogspot.com/2009/03/validate-parameters-using-attributes.html

theburningmonk
  • 15,701
  • 14
  • 61
  • 104
0

I recently released the first stable version of Guard, a library that helps you write guard clauses like these:

public ConnectionSettings(
    Uri url, string username, string password, bool checkPermissions)
{
    this.username = Guard.Argument(() => username).NotNull();
    this.password = Guard.Argument(() => password).NotNull();
    this.url = Guard.Argument(() => url).NotNull().Https();
    this.checkPermissions = checkPermissions;
}
  • It's faster than you may think, this document delves deeper into the performance considerations.
  • You can add new validations in the form of extension methods, this document explains it in detail.
Şafak Gür
  • 7,045
  • 5
  • 59
  • 96