when validating methods' input, I used to check if the argument is null, and if so I throw an ArgumentNullException. I do this for each and every argument in the list so I end up with code like this:
public User CreateUser(string userName, string password,
string Email, string emailAlerts,
string channelDescription)
{
if (string.IsNullOrEmpty(userName))
throw new ArgumentNullException("Username can't be null");
if (string.IsNullOrEmpty(Email))
throw new ArgumentNullException("Email can't be null");
//etc, etc, etc
}
Is this OK? Why should I do this? Would it be ok if I simply group all the checks and return a null value instead of throwing the exception? What is the best practice to address this situation?
PS: I want to change this, because with long methods, it gets very tedious to do so. Ideas?
Make an ArgChecker class with something like this
ArgChecker.ThrowOnStringNullOrEmpty(userName, "Username");
where ThrowOnStringNullOrEmpty is
public static void ThrowOnStringNullOrEmpty(string arg, string name)
{
if (string.IsNullOrEmpty(arg))
throw new ArgumentNullException(name + " can't be null");
}
You could also try to process a list of arguments using a params arg, like:
public static void ThrowOnAnyStringNullOrEmpty(params string[] argAndNames)
{
for (int i = 0; i < argAndName.Length; i+=2) {
ThrowOnStringNullOrEmpty(argAndNames[i], argAndNames[i+1]);
}
}
and call like this
ArgChecker.ThrowOnAnyStringNullOrEmpty(userName, "Username", Email, "email");
An approach which I use and I may have picked up from the NHibernate source is to create a static class Guard, used as follows:
public void Foo(object arg1, string arg2, int arg3)
{
Guard.ArgumentNotNull(arg1, "arg1");
Guard.ArgumentNotNullOrEmpty(arg2, "arg2");
Guard.ArgumentGreaterThan(arg3, "arg3", 0);
//etc.
}
public static class Guard
{
public static void ArgumentNotNull(object argument, string parameterName)
{
if (parameterName == null)
throw new ArgumentNullException("parameterName");
if (argument == null)
throw new ArgumentNullException(parameterName);
}
//etc.
}
This cuts down a lot of the chaff at the beginning of methods and it performs well.
You should think about the method, what it needs to do and with what data. If null values represent actual failure conditions, use exceptions. If null values are acceptable, accept them.
Think about the principles from design by contract, specifically what the preconditions to your function are, and standardize a way to enforce them (which Matt and Lou both suggest in their answers so I don't need to go into detail).
Another important thing to consider is the size of your method signatures. If you have a lot of parameters for your methods, this probably means you have bad abstractions. You can cut down on the number of parameter checks you have to make if you group parameters together in collection objects and use those objects as parameters. You can move the parameter checking to those objects instead of having to check them in every function that uses them.
So instead of passing ten related parameters to every function, figure out the few that are used in every function and package them up in an object, and include in that object methods to validate the parameters. This has the added advantage of being easy to change should the rules regarding one parameter need to be updated.
And for the C# 3.0 developers amongst us a great way to encapsulate this null checking is inside an extension method.
public void Foo(string arg1, int? arg2)
{
arg1.ThrowOnNull();
arg2.ThrowOnNull();
}
public static class extensions
{
public static void ThrowOnNull<T>(this T argument) where T : class
{
if(argument == null) throw new ArgumentNullException();
}
}
And if you wanted you could always overload that to take an argument name.
A small improvement to Lou's answer would be to use a hashtable instead, it means it checks objects aswell as just strings. Also just nicer to populate and handle in the method:
public static class ParameterChecker
{
public static void CheckForNull(Hashtable parameters)
{
foreach (DictionaryEntry param in parameters)
{
if (param.Value == null || string.IsNullOrEmpty(param.Value as string))
{
throw new ArgumentNullException(param.Key.ToString());
}
}
}
}
As you would use like:
public User CreateUser(string userName, string password, string Email, string emailAlerts, string channelDescription)
{
var parameters = new Hashtable();
parameters.Add("Username", userName);
parameters.Add("Password", password);
parameters.Add("EmailAlerts", emailAlerts);
parameters.Add("ChannelDescription", channelDescription);
ParameterChecker.CheckForNull(parameters);
// etc etc
}
I would stick with your original approach, except for just passing in the parameter name. The reason is that once you start writing those helper procedures it becomes an issue when everyone starts using different conventions for how they write the helper procedures. When someone looks over your code, they now have to check to make sure you've written the helper procedure correctly when debugging your code.
Keep checking each argument separately, though youor fingers grow weary from typing Grasshopper :) Your followers will bless you when they get the unexpected ArgumentException and are saved from a debugging run just to determine which argument failed.
My first advice to you is get ReSharper. It will tell you when there is a problem of possible null values, and when there is no need to check for them, and with the click of a mouse will add checking. Having said that...
You don't have to check for int or bool, which cannot be null.
Strings can be checked with string.IsNullOrEmpty()...
If you still decide that you want to check each and every parameter, you can either use the Command design pattern, and reflection, but your code will be unnecessarily clunky, or use the following and call it for each method:
private myType myMethod(string param1, int param2, byte[] param3)
{
CheckParameters("myMethod", {param1, param2, param3});
// rest of code...
And in your utility class put this:
///<summary>Validates method parameters</summary>
///... rest of documentation
public void CheckParameters(string methodName, List<Object> parameterValues)
{
if ( string.IsNullOrEmpty(methodName) )
throw new ArgumentException("Fire the programmer! Missing method name", "methodName"));
Type t = typeof(MyClass);
MethodInfo method = t.GetMethod(methodName);
if ( method == null )
throw new ArgumentException("Fire the programmer! Wrong method name", "methodName"));
List<ParameterInfo> params = method.GetParameters();
if ( params == null || params.Count != parameterValues.Count )
throw new ArgumentException("Fire the programmer! Wrong list of parameters. Should have " + params.Count + " parameters", "parameterValues"));
for (int i = 0; i < params.Count; i++ )
{
ParamInfo param = params[i];
if ( param.Type != typeof(parameterValues[i]) )
throw new ArgumentException("Fire the programmer! Wrong order of parameters. Error in param " + param.Name, "parameterValues"));
if ( parameterValues[i] == null )
throw new ArgumentException(param.Name + " cannot be null");
}
} // enjoy
Use an AggregateException (which is meant to contain multiple exceptions) with a list of multiple ArgumentNullException instances. Don't forget to also take advantage of the parameterName argument of ArgumentNullException which works great with nameof():
var exceptions = new List<Exceptions>();
if (firstArgument == null)
exceptions.Add(new ArgumentNullException(nameof(firstArgument), "Some optional message"));
if (secondArgument == null)
exceptions.Add(new ArgumentNullException(nameof(secondArgument), "Another optional message"));
if (exceptions.Count > 0)
throw new AggregateException(exceptions);
Related
Say I have a class
class T
{
int num;
public T(int num)
{
this.num = num;
}
public void p()
{
Console.WriteLine(this.num);
}
}
And I have a null object T t = null. Calling the method t.p() will cause a NullReferenceException no matter what.
Is it not possible to test if the object is null (by using this == null (to check if the object is null within the method)), so is there a way to set a default method that will work on a null object?
In whatever code that calls t.p() you should check if t is null. You shouldn't be calling methods on a null instance.
Regarding the second part of your question, no it is not possible to set a default method that will be called if the instance of that object is null.
I should point out that there is also the Null Object Pattern, that, depending on the exact circumstances of usage may help. I would not use it as replacement for null checks though. I've found the pattern useful in some cases.
In C/C++ you can do this, but not (easily) in C#.
For example, you might want to have a check for "if a string is empty" or "if a collection is empty", and treat a null object as meaning "empty". For this sort of case, being able to call an IsEmpty() method via a null pointer/reference results in what seems like more elegant/readable code:
if (myList.IsEmpty())
...
rather than
if (myList == null || myList.IsEmpty())
...
However, it is also extremely dangerous as it hides unusual/unexpected behaviour, and encourages the caller to stop checking for nulls. As you cannot guarantee that every method you call will protect you from nulls, how do you know that it is safe to stop checking for nulls in the calling code? Or do you check for null twice (in both the calling and called code), just in case? If you are calling many methods on the same object instance, wouldn't it be far more efficient to check for null once at the start?
So although this pattern can be used in some languages, it is not considered a good practice.
This is (one reason) why, in C#, such code is not allowed. Instead the preferred pattern is to provide a static method to check the status:
if (string.IsNullOrEmpty(myString))
....
This is only slightly less readable, but much safer as the null check is clearly visible to the reader. Even without "IsNull" in the title, tou can see that the reference is being passed to another method, and it is more reasonable to assume that the called method will be well written and check for nulls. Being transparent and explicit makes code much easier for others to read.
C# also provides the null coalescing ?? operator to make the null checks cleaner in the calling code. If you want a default to use if the object is null, then you can use this form:
string result = myString ?? string.Empty;
...which in this case will return myString if it is non-null, or string.Empty if it is null, thus guaranteeing that result is never null.
Finally, in C# 6 you can use the ?. operator, which combines an "if not null" check with an access, so you can replace:
if (element != null && element.FirstChild != null)
element.FirstChild.DoSomething();
with
element?.FirstChild?.DoSomething();
This is functionally equivalent, but a much more compact syntax.
Calling an instance method on a null reference will always result in a NullReferenceException. You have to check if the reference is not null or use the C# 6 ?. operator to do it for you.
T t = null;
t?.p(); // no method is called
You can however use an extension method on a null reference. It has some limitations, as you can only access public members in an extension method, but might be useful (especially if you cannot use C# 6 and ?.):
class T
{
public int Number { get; private set; } // public property
public T(int number)
{
Number = number;
}
}
static class Extensions
{
public static void PrintT(this T t)
{
if (t == null) Console.WriteLine("null");
else Console.WriteLine(t.Number);
}
}
T t = null;
t.PrintT(); // no exception, writes "null" to the console
It is possible to call an instance method on a null reference in CIL, simply using call instead of callvirt. The latter checks the run-time type of the referenced object, that's why it throws NRE immediately. call should call the method normally, but with the implicit this parameter set to null, and throw on first access to any member of this.
Edit
The System.Reflection.Emit namespace in C# contains types that let you dynamically emit IL. You can use it to call an instance method with a call instead of callvirt. (I modified code posted in this answer to work for methods. The sample here will only work for parameterless methods)
public static void MakeNonVirtualCall<T>(T c, Expression<Action<T>> f)
{
var expression = f.Body as MethodCallExpression;
if (expression == null) throw new ArgumentException();
var dyn = new DynamicMethod("NVCall", null, new[] { typeof(T) }, typeof(T).Module, true);
var il = dyn.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Call, expression.Method);
il.Emit(OpCodes.Ret);
((Action<T>)dyn.CreateDelegate(typeof(Action<T>)))(c);
}
Now, assuming we have a class
class Class
{
public void Method()
{
if (this == null) Console.WriteLine("`this` is null");
else Console.WriteLine("`this` is not null");
}
}
We can use it as
Class nullRef = null;
Class instance = new Class();
MakeNonVirtualCall(nullRef, t => t.Method()); // no exception, prints "`this` is null"
MakeNonVirtualCall(instance, t => t.Method()); // prints "`this` is not null"
It works - an instance method in a C# class can be called on a null reference from IL (but still not directly from C#).
Note that the MSDN documentation is incorrect here:
Calls to an instance (or virtual) method must push that instance reference before any of the user-visible arguments. The instance reference must not be a null reference.
Just check for null in the calling code.
T t = null;
// somewhere further..
if (t == null)
//t is null, don't use it
else
//save to use t
Another way (if you don't expect the object to be null is to use try/catch):
T t = null;
// somewhere further..
try {
t.p();
}
catch(NullReferenceException ex) {
// t is null
}
No you can't. And I'll tell you why. The keyword this refers to whichever object is accessing a variable or calling a method. So a this inside doSomething() would refer to object in object.doSomething().
Now coming to your question about null, when you write T t = null; it means you made a variable of type T which REFERS to NOTHING!!! And by nothing I mean, wait for it, NOTHING! Can you call methods from nothingness? NO!
I was wondering if there was some existing logic to obtain the name (or any other relevant information) about the definition of a parameter in its containing method/constructor signature by looking at an invocation of that particular method/constructor. Basically, I just want to be able to get a default name for a variable that will be passed as an argument to the invocation. So, if a method if defined as such:
public void Foo(object firstParam, object secondParam, object thirdParam)
I would want to be able to say that the second argument of the following invocation
object bar = null;
this.Foo(null, bar, null)
is expected to have the name "secondParam". Basically, I just want to relate an argument to the original parameter whose "spot" it occupies in the invocation.
I am asking if any util methods that I am not aware of already exist within Roslyn, as there are some more complex scenarios to handle, such as named or optionnal arguments. The solution I've come up with in the meantime should covers some cases, but probably not all (especially params, which should require some more specialized logic to handle). Here's what I have so far:
private IEnumerable<IdentifierNameSyntax> GetParameterNamesFromArgumentList(ArgumentListSyntax argumentList, SyntaxNodeAnalysisContext context)
{
var arguments = argumentList.Arguments;
var parameters = argumentList.Parent.GetSymbolOrDeclaredAs<IMethodSymbol>(context)?.Parameters;
if (parameters != null)
{
var index = 0;
foreach (var parameter in parameters)
{
var argument = index < arguments.Count ? arguments[index] : null;
if (argument != null && argument.NameColon == null)
{
yield return SyntaxFactory.IdentifierName(parameter.Name);
}
else if (argument != null)
{
yield return argument.NameColon.Name;
}
index++;
}
}
}
I could be using DeclaringSyntaxReferenceson the method symbol, but I think that just having the names from the IParameterSymbol suited my needs well enough. Again, if this kind of logic is already implemented anywhere else, I'd rather use it. If not, well, feel free to tell me what you think of the problem.
Sadly I don't think there is a good public way to do this. See Roslyn's internal DetermineParameter helper for something that might help.
We are trying to find a more refactor-friendly way of testing for null arguments in our methods so that instead of writing:
if (arg1 == null)
{
throw new ArgumentNullException("arg1")
}
thing1 = arg1;
our developers can do something like
thing1 = ArgumentNotNull(() => arg1);
Here is the code for ArgumentNotNull in the above example:
public static void ArgumentNotNull<T>(Expression<Func<T>> member)
where T : class
{
var argumentName = ((MemberExpression)member.Body).Member.Name;
var func = member.Compile();
var argumentValue = func();
if (argumentValue == null)
{
throw new ArgumentNullException(argumentName);
}
}
The one question I have with the way we are doing this is: Is Expression.Compile() prohibitively expensive to do for something as trivial as this check?
I have a feeling that we might see some problems down the road as both the number of arguments and calls to methods increase...
The .Compile() call is very expensive, but can be mitigated by caching the compiled method in something like a static Dictionary<TKey, TValue> where the key is the type of member. This way, your first call would be slow and the rest would be just about as fast as a regular method call, since you'd be reusing your method for future checks on a given type. Downside: possible memory bloat or leak for a lot of different types.
I've noticed this code crops up a lot in my constructors:
if (someParam == null) throw new ArgumentNullException("someParam");
if (someOtherParam == null) throw new ArgumentNullException("someOtherParam");
...
I have a few constructors where several things are injected and must all be non-null. Can anyone think of a way to streamline this? The only thing I can think of is the following:
public static class ExceptionHelpers
{
public static void CheckAndThrowArgNullEx(IEnumerable<KeyValuePair<string, object>> parameters)
{
foreach(var parameter in parameters)
if(parameter.Value == null) throw new ArgumentNullException(parameter.Key);
}
}
However, the usage of that would be something like:
ExceptionHelper.CheckAndThrowArgNullEx(new [] {
new KeyValuePair<string, object>("someParam", someParam),
new KeyValuePair<string, object>("someOtherParam", someOtherParam),
... });
... which doesn't really help streamline the code. Tuple.Create() instead of KVPs doesn't work because Tuple's GTPs aren't covariant (even though IEnumerable's GTP is). Any ideas?
Update for C# 7
You can use a throw expression with the null coalescing operator. Here is an example from that page:
public string Name
{
get => name;
set => name = value ??
throw new ArgumentNullException(paramName: nameof(value), message: "New name must not be null");
}
Original Answer
Personally, I use the ThrowIfNull extension method. I don't know who to credit but I definitely didn't invent it. It's nice because you can do assignment with the return value:
public static T ThrowIfNull<T>(this T argument, string argumentName)
{
if (argument == null)
{
throw new ArgumentNullException(argumentName);
}
return argument;
}
Usage:
this.something = theArgument.ThrowIfNull("theArgument");
// or in C# 6
this.something = theArgument.ThrowIfNull(nameof(theArgument));
(Although some people think it's weird to call an extension method on a null instance)
If you really want to check more than one argument at a time, your example might be more streamlined if you used a params signature like so:
public static void CheckAndThrowArgNullEx(params object[] argsAndNames)
{
for (int i = 0; i < argsAndNames.Length; i += 2)
{
if (argsAndNames[i] == null)
{
string argName = (string)argsAndNames[i + 1];
throw new ArgumentNullException(argName);
}
}
}
and the usage would be:
CheckAndThrowArgNullEx(arg1, "arg1", arg2, "arg2");
// or in C# 6
CheckAndThrowArgNullEx(arg1, nameof(arg1), arg2, nameof(arg2));
On second thought, as KeithS mentions in the comments, it would probably be better to implement this as a set of overloads rather than using params object[] like this:
static void Check(object arg1, string arg1Name) { ... }
static void Check(object arg1, string arg1Name, object arg2, string arg2Name) { ... }
// and so on...
Try this: One line.
accounts = accounts ?? throw new ArgumentNullException(nameof(accounts));
Also, use nameof(), if the variable is ever renamed you will not have to hunt down all the "variable"s, let nameof() do that.
.NET 6 and beyond
There is a new method in .NET API ArgumentNullException.ThrowIfNull(someParameter).
This method is probably the best option which you can get.
C# 11 (currently as proposal)
Use new Bang Bang operator !! on a parameter to implicit check for null.
public string SomeFunction(Foo foo!!)
{
// here, foo is already checked for null
// ArgumentNullException(nameof(foo)) is thrown when foo = null
return $"Here is {foo.Bar}";
}
TL;DR
The compiler will emit this code for every !! use
if (someArgument is null)
{
throw new ArgumentNullException(nameof(someArgument));
}
Our SomeFunction will be transformed into
public string SomeFunction(Foo foo!!)
{
if (foo is null)
{
throw new ArgumentNullException(nameof(foo));
}
return $"Here is {foo.Bar}";
}
There are several way to go about this.
Option A:
Break your functions into two - validation and implementation (you can see examples of this in Jon Skeet's EduLinq).
Option B:
Use code contracts that expect the parameters to be non-null.
Option C:
Using aspect oriented technologies such as code weaving to extract these checks out into an aspect. (as J Torres answered).
Option D:
Use Spec#, as CodeInChaos commented.
Option E:
???
Upticks for most of you guys; your answers contributed to the solution I finally arrived at, which incorporated bits and pieces but ultimately is different from all of them.
I created a couple of static methods that work on lambda expressions of a specific form (EDIT - small change; the methods can't be generic or they will require all expressions to return the same type. Func is fine instead, with an extra condition in the GetName method to unwrap the cast):
public static class ExpressionReader
{
/// <summary>
/// Gets the name of the variable or member specified in the lambda.
/// </summary>
/// <param name="expr">The lambda expression to analyze.
/// The lambda MUST be of the form ()=>variableName.</param>
/// <returns></returns>
public static string GetName(this Expression<Func<object>> expr)
{
if (expr.Body.NodeType == ExpressionType.MemberAccess)
return ((MemberExpression) expr.Body).Member.Name;
//most value type lambdas will need this because creating the
//Expression from the lambda adds a conversion step.
if (expr.Body.NodeType == ExpressionType.Convert
&& ((UnaryExpression)expr.Body).Operand.NodeType
== ExpressionType.MemberAccess)
return ((MemberExpression)((UnaryExpression)expr.Body).Operand)
.Member.Name;
throw new ArgumentException(
"Argument 'expr' must be of the form ()=>variableName.");
}
}
public static class ExHelper
{
/// <summary>
/// Throws an ArgumentNullException if the value of any passed expression is null.
/// </summary>
/// <param name="expr">The lambda expressions to analyze.
/// The lambdas MUST be of the form ()=>variableName.</param>
/// <returns></returns>
public static void CheckForNullArg(params Expression<Func<object>>[] exprs)
{
foreach (var expr in exprs)
if(expr.Compile()() == null)
throw new ArgumentNullException(expr.GetName());
}
}
... which can be used thusly:
//usage:
ExHelper.CheckForNullArg(()=>someParam, ()=>someOtherParam);
This reduces the boilerplate to one line, without third-party tools. The ExpressionReader, and thus the exception-generating method, work on any lambda of the form ()=>variableName that compiles in the caller, meaning it works for local variables, parameters, instance fields and instance properties, at least. I haven't checked to see if it works on statics.
In c# 10 you can just do this:
ArgumentNullException.ThrowIfNull(z);
And you will got this error:
System.ArgumentNullException: Value cannot be null. (Parameter 'z')
at System.ArgumentNullException.Throw(String paramName)
at System.ArgumentNullException.ThrowIfNull(Object argument, String paramName)
at ConsoleApp1.SomeClass.Join(String a, String b)
Under the hood, it use the new CallerArgumentExpression attribure.
public class TestClass
{
public TestClass()
{
this.ThrowIfNull(t=>t.Str, t=>t.Test);
//OR
//this.ThrowIfNull(t => t.X)
// .ThrowIfNull(t => t.Test);
}
string Str = "";
public TestClass Test {set;get;}
}
public static class SOExtension
{
public static T ThrowIfNull<T>(this T target, params Expression<Func<T, object>>[] exprs)
{
foreach (var e in exprs)
{
var exp = e.Body as MemberExpression;
if (exp == null)
{
throw new ArgumentException("Argument 'expr' must be of the form x=>x.variableName");
}
var name = exp.Member.Name;
if (e.Compile()(target) == null)
throw new ArgumentNullException(name,"Parameter [" + name + "] can not be null");
}
return target;
}
}
In c# 7 can be done like this:
_ = someParam ?? throw new ArgumentNullException(nameof(someParam));
After release optimisation you will get:
if (someParam == null)
throw new ArgumentNullException(nameof(someParam));
If you aren't opposed to third party utilities, PostSharp provides clean ways to inject such validations. This blog post provides a solution to your problem.
Update: See new Validating-parameters features in PostSharp 3
How about an extension method?
public static void ThrowExceptionIfNull(this object argument, string argumentName)
{
if(argument == null)
throw new ArgumentNullException(argumentName);
}
Then your code at least reads a little more fluently:
someParam.ThrowExceptionIfNull("someParam");
Otherwise, I would agree with the others to split the functionality or use AOP (ie. PostSharp)
Well, the boilerplate is hard to avoid. You could switch to using the Bertrand Meyers' Eiffel programming language and EiffelStudio instead of C# and Visual Studio and start practicing "design by contractâ„¢".
Eiffel is fully CLR-compliant these days.
There are a lot of valid solutions already, but here's my take:
using System.Diagnostics;
using System.Reflection;
public SomeConstructor(int? par1, int? par2, string par3)
{
CheckThrowNull(par1, par2, par3);
//rest of constructor code...
}
///<param name="values"> Values must be given in order </param>
public static void CheckThrowNull(params object[] values)
{
StackTrace stackTrace = new StackTrace();
ParameterInfo[] parameters = stackTrace.GetFrame(1).GetMethod().GetParameters(); //get calling method's parameters (or constructor)
if (parameters.Length != values.Length)
{
throw new ArgumentException("Incorrect number of values passed in");
}
for (int i = 0; i < parameters.Length; i++)
{
if (values[i] == null)
{
//value was null, throw exception with corresponding parameter name
throw new ArgumentNullException(parameters[i].Name);
}
}
}
The general idea is that two parallel arrays are established, one of type ParameterInfo, and one containing the values of the parameter. The latter has to passed in because parameter values aren't easily (and I think impossible) obtainable via reflection. To give credit where it is due, I found how to get the calling method here: http://www.csharp-examples.net/reflection-calling-method-name/
Personally, I don't like using System.Diagnosics except for debugging, so I would make a slight modification, having calling code be:
CheckThrowNull(MethodBase.GetCurrentMethod(), par1, par2, par3);
and the method being
CheckThrowNull(MethodBase method, params object[] values)
{
ParameterInfo[] parameters = method.GetParameters();
//rest of code same
}
The down-side is its a little non-extensible and can't easily be made to check if just some of the arguments are null.
I wrote benchmark application with multiple variations of extracting argument name (via anonymous class + reflection / MemberExpression / Func / etc)
Github link to benchmark sources: https://github.com/iXab3r/NullCheckCompetition
I got results, that are showing, that the fastest method is through use of anonymous class.
.NET 40 / X64
Fail (i.e. argument IS null and name extraction method is executed)
FailAnonymousClass 67.87 ns
FailDoubleLambda 643.98 ns
FailLazyAnonymousClass 69.36 ns
FailRawCheck 1.08 ns
FailSingleLambda 643.27 ns
Success (i.e. argument is not null)
SuccessAnonymousClass 6.33 ns
SuccessDoubleLambda 8.48 ns
SuccessLazyAnonymousClass 8.78 ns
SuccessRawCheck 1.08 ns
SuccessSingleLambda 628.28 ns
I think most of the above are ok but none of them are really an improvement to what you already have so I would just go for the KIS, Keep It Simple, and that is what you started with.
It's clean, extremly readable and its fast. The only thing it's a bit long
Update for C# 10 (.NET >= 6):
_person = person.ThrowIfNull();
public static T ThrowIfNull<T>(this T? argument, string? message = default, [CallerArgumentExpression("argument")] string? paramName = default)
{
return argument ?? throw new ArgumentNullException(paramName, message);
}
Reference:
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/caller-argument-expression
With C# 11 and .NET 6.0 you can do this:
public bool DoSomething(string name)
{
ArgumentNullException.ThrowIfNull(name);
// Do your stuff, name is not null
}
ArgumentNullException.ThrowIfNull Method
It is actually possible to retrieve the argument name from the lambda expression without going through the Expression type. This is how it can be done:
static void SampleMethod(string arg1)
{
ThrowIfNull(() => arg1);
// continue to other normal stuff here...
}
public static void ThrowIfNull<T>(Func<T> lambda)
where T : class
{
if (lambda() == null)
{
throw new ArgumentNullException(lambda.Target.GetType().GetFields()[0].Name);
}
}
I'm writing an application that runs "things" to a schedule.
Idea being that the database contains assembly, method information and also the parameter values. The timer will come along, reflect the method to be run, add the parameters and then execute the method.
Everything is fine except for the parameters.
So, lets say the method accepts an ENUM of CustomerType where CustomerType has two values of CustomerType.Master and CustomerType.Associate.
EDIT
I don't know the type of parameter that will be getting passed in. ENUM used as an example
END OF EDIT
We want to run Method "X" and pass in parameter "CustomerType.Master". In the database, there will be a varchar entry of "CustomerType.Master".
How do I convert the string "CustomerType.Master" into a type of CustomerType with a value of "Master" generically?
Thanks in advance,
Jim
OK, the scope of the question shifted but my original observation and objection to some other solutions still stands.
I think you don't/can't want to use 'generics' here. You don't know the type ahead of time, and since you will need to create the type, there is no need to use a generic implementation because MethodBase.Invoke takes an array of Object.
This code assumes you are instantiating the target from database field. If not just adjust accordingly.
Of course this is not all encompassing and has no useful exception handling, but it will allow you to dynamically execute arbitrary methods on an arbitrary type with arbitrary parameters values all coming from string values in a row.
NOTE: there are many many many scenarios in which this simple executor will not work. You will need to ensure that you engineer your dynamic methods to cooperate with whatever strategy you do end up deciding to use.
using System;
using System.ComponentModel;
using System.Drawing;
using System.Globalization;
using System.Reflection;
using NUnit.Framework;
namespace DynamicMethodInvocation
{
[TestFixture]
public class Tests
{
[Test]
public void Test()
{
// from your database
string assemblyQualifiedTypeName = "DynamicMethodInvocation.TestType, DynamicMethodInvocation";
string methodName = "DoSomething";
// this is how you would get the strings to put in your database
string enumString = Executor.ConvertToString(typeof(AttributeTargets), AttributeTargets.Assembly);
string colorString = Executor.ConvertToString(typeof(Color), Color.Red);
string stringString = "Hmm... String?";
object result = Executor.ExecuteMethod(assemblyQualifiedTypeName, methodName,
new[] { enumString, colorString, stringString });
Assert.IsInstanceOf<bool>(result);
Assert.IsTrue((bool)result);
}
}
public class TestType
{
public bool DoSomething(AttributeTargets #enum, Color color, string #string)
{
return true;
}
}
public class Executor
{
public static object ExecuteMethod(string assemblyQualifiedTypeName, string methodName,
string[] parameterValueStrings)
{
Type targetType = Type.GetType(assemblyQualifiedTypeName);
MethodBase method = targetType.GetMethod(methodName);
ParameterInfo[] pInfo = method.GetParameters();
var parameterValues = new object[parameterValueStrings.Length];
for (int i = 0; i < pInfo.Length; i++)
{
parameterValues[i] = ConvertFromString(pInfo[i].ParameterType, parameterValueStrings[i]);
}
// assumes you are instantiating the target from db and that it has a parameterless constructor
// otherwise, if the target is already known to you and instantiated, just use it...
return method.Invoke(Activator.CreateInstance(targetType), parameterValues);
}
public static string ConvertToString(Type type, object val)
{
if (val is string)
{
return (string) val;
}
TypeConverter tc = TypeDescriptor.GetConverter(type);
if (tc == null)
{
throw new Exception(type.Name + " is not convertable to string");
}
return tc.ConvertToString(null, CultureInfo.InvariantCulture, val);
}
public static object ConvertFromString(Type type, string val)
{
TypeConverter tc = TypeDescriptor.GetConverter(type);
if (tc == null)
{
throw new Exception(type.Name + " is not convertable.");
}
if (!tc.IsValid(val))
{
throw new Exception(type.Name + " is not convertable from " + val);
}
return tc.ConvertFrom(null, CultureInfo.InvariantCulture, val);
}
}
}
I would think you have 2 major options:
Store the type name along with the parameter value and use that to cast things using Type.GetType(string) to resolve the type in question.
Standardize all the methods to be called this way to accept an array of strings, and expect the methods to do any necessary casting.
I know you've stated that you're not doing option 1, but it would help things from the standpoint of calling the functions.
Option 2 is the far more 'generic' way to handle the situation, assuming all values can be represented by and cast/converted from strings to the appropriate type. Of course, that only helps if you actually have control over the definition of the methods being called.
Below is a useful extension method I use in .NET 3.5.
With this extension method available, your code could look like this:
var valueInDb = GetStringFromDb().Replace("CustomerType.", string.Empty);
var value = valueInDb.ToEnum(CustomerType.Associate);
By supplying the default value in the parameter, the compiler will know which Enum you want your string to be turned into. It will try to find your text in the Enum. If it doesn't it will return the default value.
Here is the extension method: (this version also does partial matches, so even "M" would work nicely!)
public static T ToEnum<T>(this string input, T defaultValue)
{
var enumType = typeof (T);
if (!enumType.IsEnum)
{
throw new ArgumentException(enumType + " is not an enumeration.");
}
// abort if no value given
if (string.IsNullOrEmpty(input))
{
return defaultValue;
}
// see if the text is valid for this enumeration (case sensitive)
var names = Enum.GetNames(enumType);
if (Array.IndexOf(names, input) != -1)
{
// case insensitive...
return (T) Enum.Parse(enumType, input, true);
}
// do partial matching...
var match = names.Where(name => name.StartsWith(input, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
if(match != null)
{
return (T) Enum.Parse(enumType, match);
}
// didn't find one
return defaultValue;
}
I still don't fully understand your question... however, you say "Everything is fine except for the parameters."
I'll assume "CustomerType" the name of a property on your object, and "Master" is the string value you want to put in that property.
Here is (another) extension method that may help.
Once you have your new object and the value and property name from the database field, you could use this:
// string newValue = "Master";
// string propertyName = "CustomerType";
myNewObject.SetPropertyValue(propertyName, newValue)
Method:
/// <summary>Set the value of this property, as an object.</summary>
public static void SetPropertyValue(this object obj,
string propertyName,
object objValue)
{
const BindingFlags attr = BindingFlags.Public | BindingFlags.Instance;
var type = obj.GetType();
var property = type.GetProperty(propertyName, attr);
if(property == null) return;
var propertyType = property.PropertyType;
if (propertyType.IsValueType && objValue == null)
{
// This works for most value types, but not custom ones
objValue = 0;
}
// need to change some types... e.g. value may come in as a string...
var realValue = Convert.ChangeType(objValue, propertyType);
property.SetValue(obj, realValue, null);
}
If you are using .NET 4 you can do the following.
var result = default(CustomerType);
if (!Enum.TryParse("Master", out result))
{
// handle error
}