简体   繁体   中英

How to check for null parameter values

I have the method below and I want to check if any of the parameters are null. If any are null, I want to be able to print an error that says something like: "'name' is missing" with the correct variable displayed.

public void Method(string name, DateTime? date)
{  }

I need to be able to use my own custom error handling, so nothing built in like ArgumentNullException. I know an if statement can be used, but I was hoping to use some sort of validator. Is there a way to do this so that it can be used across multiple methods and returns the correct variable name in the message?

Aspect oriented programming is the usual way to approach such requirements in a generic way. You may want to have a look at PostSharp , Castle DynamicProxy or Microsoft's Unity and there are a couple of other alternatives. But this is a huge hammer, think carefully before using it.

For your specific problem compile time weaving would be sufficient and require no code changes or at most adding some attributes but it requires changes to your build process. Run time weaving will not affect your build process but will probably require a non-trivial amount of code changes.

PostSharp Ultimate includes the aspect you want , at least almost, or you can buy it separately and probably use with the free edition. But it is not hard to implement it on your own.

I don't know if this is what you looked for, but did you hear about design by contract ?

Check the official code contracts' article on MSDN.

One of possible use cases of code contracts is parameter validation.

For example, your code would look like this:

public void Method(string name, DateTime? date)
{  
     Contract.Requires(!string.isNullOrEmpty(name), "'name' cannot be null");
     Contract.Requires(date.HasValue, "'date' is required");
}

You can also listen for contract exceptions using a global contract handler .

If you look further at code contracts, you'll find that you can create contracts for interfaces and abstract class so any implementation will get their contracts injected in their body.

From what i understand, you are looking for something like this.

Console Output:

Method: test, Parameter: a has a null value
False
Method: test, Parameter: b has a null value
False
True

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {

            Console.WriteLine(test("", "Something").ToString());
            Console.WriteLine(test("something", null, "blah").ToString());
            Console.WriteLine(test("something", "blah", "blah").ToString());
            Console.ReadLine();
        }

        public static bool test(string a, string b)
        {
            if (Validator.isNullOrEmpty(MethodBase.GetCurrentMethod(), a, b))
                return false;
            return true;
        }
        public static bool test(string a, string b, string c)
        {
            if (Validator.isNullOrEmpty(MethodBase.GetCurrentMethod(), a, b, c))
                return false;
            return true;
        }
    }

    class Validator
    {
        public static bool isNullOrEmpty(MethodBase method, params object[] values)
        {
            ParameterInfo[] pars = method.GetParameters();
            bool ret = false;
            for(var i = 0; i < pars.Length; i++)
            {
                ParameterInfo p = pars[i];
                string type = p.ParameterType.ToString().ToLower();
                try
                {
                    switch (type)
                    {
                        case "system.string":
                            ret = String.IsNullOrEmpty((string)values[i]);
                            break;
                        case "system.int32":
                        case "system.double":
                        default:
                            ret = values[i] != null;
                            break;
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(String.Format("Method: {0}, Parameter: {1} has an incorrect value for a {2} with '{3}'",
                        method.Name, p.Name, type, values[i]));
                    Console.WriteLine(ex.Message);
                    return true;
                }
                if (ret)
                {
                    Console.WriteLine(String.Format("Method: {0}, Parameter: {1} has a null value", method.Name, p.Name));
                    return ret;
                }
            }

            return ret;
        }
    }
}

For the string:

if(string.IsNullOrEmpty(name))

For the nullable:

if(date.HasValue)
public void Method(string name, DateTime? date)
{
    if( name == null ){ } // you may want: if( string.IsNullOrEmpty( name ) ){}
    if( date.HasValue ){ }
}

This is the solution I went with to avoid installing any new products and learning new technologies. @Daniel had some great suggestions that probably would work the best for this issue, but following the steps on this post I was able to get it to work in a similar way to what I was hoping for.

http://weblogs.asp.net/fredriknormen/archive/2008/05/08/how-to-validate-a-method-s-arguments.aspx

In addition, here is another interesting solution, although it requires an interceptor from Microsoft's Unity:

http://www.codinginstinct.com/2008/05/argument-validation-using-attributes.html

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM