4

At the moment i am using this code in a class i call "Ensure", it is essentially a shortcut class of static methods i use to make throwing exceptions easier, so i am not constantly having to write out a minimum of 3 lines to do an exception, it can all always be done on 1 line.

 [DebuggerHidden, DebuggerStepThrough] public static void ArgumentNotNull(object argument, string name) { if (argument == null) { throw new ArgumentNullException(name, "Cannot be null"); } } [DebuggerHidden, DebuggerStepThrough] public static void ArgumentNotNull<T>(Expression<Func<T>> expr) { var e = (MemberExpression)expr.Body; var val = GetValue<T>(e); ArgumentNotNull(val, e.Member.Name); } 

My issue is, currently when calling Ensure.ArgumentNotNull, i either have to do:

Ensure.ArgumentNotNull(arg, "arg"); 

or

Ensure.ArgumentNotNull(() => arg); 

As i need the name to be able to explain which argument caused the exception in the exception its self.

Is there a way of being able to call ArgumentNotNull without needing the () => part of the lambda and simply call Ensure.ArgumentNotNull(arg) and still be able to get the name of the argument that was passed, without having to specifically pass the name as well.

5
  • 2
    You can always wait for C# 6.0; you'll have nameof expressions. Commented Nov 6, 2014 at 14:46
  • 2
    @DStanley: its not that its a burden, it just doesnt look as clean as it could, and it was a speculative question anyway, i asked because i didnt know the answer. Commented Nov 6, 2014 at 14:55
  • Have you thought about using Fody for AOP to add Ensure at build type. Alternatively you could consider using Code Contracts and the Static Code Analysis to "prove" that the arg is never null. Commented Nov 6, 2014 at 16:34
  • @Aron: no, i havnt, because that isnt what i am trying to achieve. Commented Nov 7, 2014 at 15:27
  • @bizzehdee You should take a look at this... github.com/Fody/NullGuard Commented Nov 7, 2014 at 18:54

4 Answers 4

2

Is there a way of being able to call ArgumentNotNull without needing the () => part of the lambda and simply call Ensure.ArgumentNotNull(arg) and still be able to get the name of the argument that was passed

I doubt it, because values have no meta-data to determine if it was an argument passed in, a variable, or a literal. The value will not always be an argument - there's nothing preventing you from calling Ensure.ArgumentNotNull(null);.

Sign up to request clarification or add additional context in comments.

5 Comments

That will change in C# 6.0 with nameof expressions. I think the needed infrastructure has been there for a while but the language never leveraged it.
@InBetween Will it? You would still have to pass in the second parameter - Ensure.ArgumentNotNull(arg, nameof(arg)); nameof has no magic to tell the function that the value passed in was named arg in the calling function.
@ChrisMcKelt The OP's question contains the code to do that.
@DStanley Very true, I stand corrected, you'd still need two arguments.
But the value here is, if the variable is renamed, and the code compiles (which allows us to presume that the variable was renamed in all locations), then the second parameter will always be correct, instead of perhaps staying the old and incorrect parameter name.
0

this works

public static void ArgumentNotNull(object argument) { StackFrame stackFrame = new StackTrace(true).GetFrame(1); string fileName = stackFrame.GetFileName(); int lineNumber = stackFrame.GetFileLineNumber(); var file = new System.IO.StreamReader(fileName); for (int i = 0; i < lineNumber - 1; i++) file.ReadLine(); string varName = file.ReadLine().Split(new char[] { '(', ')' })[1]; if (argument == null) { throw new ArgumentNullException(varName, "Cannot be null"); } } 

alternate answer to OP question

 'and still be able to get the name of the argument that was passed, without having to specifically pass the name as well.' 

Simplified lamdba will do the trick.

myObject.ArgumentNotNull(x=>x.SomeProperty); -- prop checking myObject.ArgumentNotNull(x=>x); -- objchecking [DebuggerHidden, DebuggerStepThrough] public static void ArgumentNotNull<T>(this T obj, Expression<Func<T, object>> expr = null) { if (obj == null) throw new NullReferenceException(); var body = expr.Body as MemberExpression; if (body == null) { var ubody = (UnaryExpression)expr.Body; body = ubody.Operand as MemberExpression; } if (body != null) { var property = body.Member as PropertyInfo; if (property == null) throw; if (obj.GetType().GetProperty(property.Name).GetValue(obj, null) == null) throw new NullReferenceException(); } else { var ubody = (UnaryExpression)expr.Body; var property = ubody.Operand as MemberExpression; if (property != null) props[property.Member.Name] = obj.GetType() .GetProperty(property.Member.Name) .GetValue(obj, null); if (obj.GetType().GetProperty(property.Member.Name).GetValue(obj, null) == null) throw new NullReferenceException(); } } 

7 Comments

good write up on how to get property name/value via lambda expressions here - joelabrahamsson.com/…
OP was asking how to get the argument name without passing in a lambda.
Yes, but the OP already has a method to do it with a lambda (albeit more rudimentary than yours) but wants to be able to just pass the value.
@DStanley updated answer with a solution that works (no lambdas) - inspired in part from here - stackoverflow.com/questions/1718037/…
Stack approach, if I remember correctly, will not necessarily work with release builds.
|
0

I am not aware of any mechanism you could use for this without some degree of code clutter, except for the Fody.NullGuard mentioned by Aron (opt-out model only) and other AOP frameworks (PostSharp).

However, instead of using expression trees, which both result in significant runtime performance penalty and are limited in terms of syntax, you can use anonymous types. This approach is relatively good in terms of performance, with a couple of assumptions:

  • that the user of the API will use it for arguments assertion only
  • that details of anonymous types implementation in C# will not change significantly

The usage of the API will look something like:

void SomeMethod(object arg1, string arg2, List<int> arg3) { new { arg1, arg2, arg3 }.ShouldNotBeNull(); .... 

Implementation is too large to show here, so it can be found in this gist. Additionally, it can be extended for range validations, etc.

Comments

-1

You really want to use Fody.NullGuard instead of your current solution if you are worried about making a mistake when calling throw new ArgumentNullException("argName");.

You use Fody.NullGuard like this

public class Sample { public void SomeMethod(string arg) { // throws ArgumentNullException if arg is null. } public void AnotherMethod([AllowNull] string arg) { // arg may be null here } } 

After compilation, Fody will rewrite the IL so its functionally the same as

public class Sample { public void SomeMethod(string arg) { if(arg == null) throws new ArgumentNullException("arg"); } public void AnotherMethod(string arg) { } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.