A common problem in any language is to assert that parameters sent in to a method meet your requirements, and if they don't, to send nice, informative error messages. This kind of code gets repeated over and over, and we often try to create helpers for it. However, in C#, it seems those helpers are forced to deal with some duplication forced upon us by the language and compiler. To show what I mean, let me present some some raw code with no helpers, followed by one possible helper. Then, I'll point out the duplication in the helper and phrase my question precisely.
First, the code without any helpers:
public void SomeMethod(string firstName, string lastName, int age) { if(firstName == null) { throw new WhateverException("The value for firstName cannot be null."); } if(lastName == null) { throw new WhateverException("The value for lastName cannot be null."); } // Same kind of code for age, making sure it is a reasonable range (< 150, for example). // You get the idea }
}
Now, the code with a reasonable attempt at a helper:
public void SomeMethod(string firstName, string lastName, int age) { Helper.Validate( x=> x !=null, "firstName", firstName); Helper.Validate( x=> x!= null, "lastName", lastName); }
The main question is this: Notice how the code has to pass the value of the parameter and the name of the parameter ("firstName" and firstName). This is so the error message can say, "Blah blah blah the value for the firstName parameter." Have you found any way to get around this using reflection or anything else? Or a way to make it less painful?
And more generally, have you found any other ways to streamline this task of validating parameters while reducing code duplication?
EDIT: I've read people talking about making use of the Parameters property, but never quite found a way around the duplication. Anyone have luck with that?
Thanks!
You should check out Code Contracts; they do pretty much exactly what you're asking. Example:
[Pure] public static double GetDistance(Point p1, Point p2) { CodeContract.RequiresAlways(p1 != null); CodeContract.RequiresAlways(p2 != null); // ... }
Wow, I found something really interesting here. Chris above gave a link to another Stack Overflow question. One of the answers there pointed to a blog post which describes how to get code like this:
public static void Copy<T>(T[] dst, long dstOffset, T[] src, long srcOffset, long length) { Validate.Begin() .IsNotNull(dst, “dst”) .IsNotNull(src, “src”) .Check() .IsPositive(length) .IsIndexInRange(dst, dstOffset, “dstOffset”) .IsIndexInRange(dst, dstOffset + length, “dstOffset + length”) .IsIndexInRange(src, srcOffset, “srcOffset”) .IsIndexInRange(src, srcOffset + length, “srcOffset + length”) .Check(); for (int di = dstOffset; di < dstOffset + length; ++di) dst[di] = src[di - dstOffset + srcOffset]; }
I'm not convinced it is the best answer yet, but it certainly is interesting. Here's the blog post, from Rick Brewster.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With