I'd like to know if there is a way to throw an exception from inside a method, but to not include that method in the exception stack trace. E.g.
void ThrowSomeException()
{
throw new SomeException();
}
And then, if I call that method from a method called Foo() I want the exception stack trace to start with at Foo(), not at ThrowSomeException(). I assume if this was possible it might be through the use of attributes on the method.
I'm interested in the general answer, but in case this isn't possible, what I'm really trying to do is create an extension method AssertEqual() for IEnumerable that I'll use in NUnit tests. So when I call myEnumerable.AssertEqual(otherEnumerable) and it fails, NUnit should report the error inside the test method, not inside the extension method.
Thanks!
Using the code at the end of this answer allows you to write code such as:
[HideFromStackTrace] // apply this to all methods you want omitted in stack traces
static void ThrowIfNull(object arg, string paramName)
{
if (arg == null) throw new ArgumentNullException(paramName);
}
static void Foo(object something)
{
ThrowIfNull(something, nameof(something));
…
}
static void Main()
{
try
{
Foo(null);
}
catch (Exception e)
{
Console.WriteLine(e.GetStackTraceWithoutHiddenMethods());
} // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
} // gets a stack trace string representation
// that excludes all marked methods
Here's one possible implementation:
using System;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
[AttributeUsage(AttributeTargets.Method, Inherited=false)]
public class HideFromStackTraceAttribute : Attribute { }
public static class MethodBaseExtensions
{
public static bool ShouldHideFromStackTrace(this MethodBase method)
{
return method.IsDefined(typeof(HideFromStackTraceAttribute), true);
}
}
public static class ExceptionExtensions
{
public static string GetStackTraceWithoutHiddenMethods(this Exception e)
{
return string.Concat(
new StackTrace(e, true)
.GetFrames()
.Where(frame => !frame.GetMethod().ShouldHideFromStackTrace())
.Select(frame => new StackTrace(frame).ToString())
.ToArray()); // ^^^^^^^^^^^^^^^ ^
} // required because you want the usual stack trace
} // formatting; StackFrame.ToString() formats differently
Note that this only causes marked methods to be excluded from one particular representation of the stack trace, not from the stack trace itself. I know of no way to achieve the latter.
P.S.: If all you want is to hide a method in the Call Stack window during a debugging session, simply apply the [DebuggerHidden] attribute to the method.
Maybe you could derive your own exception type and override the StackTrace property getter to exclude your method:
using System;
using System.Collections.Generic;
class MyException : Exception {
string _excludeFromStackTrace;
public MyException(string excludeFromStackTrace) {
_excludeFromStackTrace = excludeFromStackTrace;
}
public override string StackTrace {
get {
List<string> stackTrace = new List<string>();
stackTrace.AddRange(base.StackTrace.Split(new string[] {Environment.NewLine},StringSplitOptions.None));
stackTrace.RemoveAll(x => x.Contains(_excludeFromStackTrace));
return string.Join(Environment.NewLine, stackTrace.ToArray());
}
}
}
class Program {
static void TestExc() {
throw new MyException("Program.TestExc");
}
static void foo() {
TestExc();
}
static void Main(params string[] args) {
try{
foo();
} catch (Exception exc){
Console.WriteLine(exc.StackTrace);
}
}
}
This is now built-in starting with .NET 6 using the StackTraceHiddenAttribute
https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.stacktracehiddenattribute?view=net-6.0
[StackTraceHidden]
void ThrowSomeException()
{
throw new SomeException();
}
I am guessing that you want to do this in order to consolidate code that is used to create the exception? In that case, rather than write a ThrowException() function, why not write a GetException() function? Then in Foo, just do throw GetException();
The GetStackTraceWithoutHiddenMethods() extension method answer is fine, except that Exception.ToString() doesn't use the StackTrace property, it calls GetStackTrace() instead, which isn't overrridable. So, if one wishes to use this extension method with their own Exception based types, they have to override ToString() rather than overriding the StackTrace property.
Perhaps in a near futur, you could use [StackTraceHidden]. For now, System.Diagnostics.StackTraceHiddenAttribute is internal but Consider exposing System.Diagnostics.StackTraceHiddenAttribute publicly is on the go.
Please note that this is an improvement to the existing answers.
The Accepted answer of this question is really clumsy because
It determines the method that we need to hide from stack trace by its name using pure string.
Splitting the stack trace is based on the string.Split method.
It hides just one method from StackTrace property, No more.
But it overrides StackTrace property itself (which the desired behavior of the question)
The Most Upvoted Answer is really cleaner because
it is using an attribute instead of specifying the name of the method as a string.
It could be used to hide more than one method from the StackTrace.
but it really complicated and adding two more classes just
for extension methods.
And the most important weak point in it is not overriding
the StackTrace property itself.
After reading the previous two solutions, I think I reached to the simplest AND most clean way (which combine the best of the two top answer to this question)
here is the infrastructure that needed.
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
public sealed class StackTraceHiddenAttribute : Attribute
{
}
public class SomeException : Exception
{
public override string StackTrace
{
get
{
return string.Concat(
new StackTrace(this, true)
.GetFrames()
.Where(frame => !frame.GetMethod().IsDefined(typeof(StackTraceHiddenAttribute), true))
.Select(frame => new StackTrace(frame).ToString())
.ToArray());
}
}
}
and here is an example of using the previous infrastructure
[StackTraceHidden] // apply this to all methods you want to be omitted in stack traces
static void Throw()
{
throw new SomeException();
}
static void Foo()
{
Throw();
}
static void Main()
{
try
{
Foo();
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
}
}
EDIT
According to a comment by #Stakx on this answer, which is deleted immediately after putting it, he points out to some important idea:
This solution works only for the custom defined exceptions, and his solution working on all exceptions types, which is absolutely correct.
According to that, here is one extension method, without much more complex, which could solve the problem and work on all the exception types.
public static class ExceptionExtensions
{
public static string GetStackTraceWithoutHiddenMethods(this Exception e)
{
return string.Concat(
new StackTrace(e, true)
.GetFrames()
.Where(frame => !frame.GetMethod().IsDefined(typeof(StackTraceHiddenAttribute), true))
.Select(frame => new StackTrace(frame).ToString())
.ToArray());
}
}
which is almost identical to his code, except integrating the IsDefined method.
I created an extension method according with the StriplingWarrior solution and worked perfectly.
public static class ExceptionExtensions
{
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Throw(this Exception exception) => throw exception;
}
and then we can use it...
using static SomeNamespace.ExceptionExtensions;
public class SomeClass
{
private void SomeMethod(string value)
{
var exception = GetArgumentException(nameof(value), value);
exception?.Throw(); // only throw if any exception was getted
... //method implementation
}
private Exception GetArgumentException(string paramName, string value)
{
if (value == null)
return new ArgumentNullException(paramName);
if (string.IsNullOrEmpty(value))
return new ArgumentException("value is empty.", paramName);
return null;
}
}
With that the Throw() method will not appear in the stack trace.
If you tell the compiler to aggressively inline your method, it should prevent your method from ever making it to the call stack in the first place:
[MethodImpl(MethodImplOptions.AggressiveInlining)]
void ThrowSomeException()
{
throw new SomeException();
}
This attribute is available as of .NET 4.5.
However, this is only considered a strong hint to the compiler, and in some cases it still doesn't cause inlining. For example, I don't think it can inline it if you call the method from a different assembly, or if you compile in debug mode.
One workaround for this could be to only create the exception with your helper, and throw it from the calling code.
public static InvalidOperationException InvalidOperation(FormattableString message)
{
return new InvalidOperationException(FormattableString.Invariant(message));
}
// calling code
throw ExceptionHelpers.InvalidOperation($"{0} is not a valid value", value);
But if your helper method has logic to determine whether to throw the exception, that might not work out for you:
public static class Require
{
[ContractAnnotation("condition:false => halt")]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[DebuggerHidden]
public static void True(bool condition)
{
if (!condition)
{
throw ExceptionHelpers.InvalidOperation($"Expected condition was not met.");
}
}
}
In those cases, you'll probably have to muck with the exception stack traces as the other answers here show. For example, you may want to ignore methods marked with the DebuggerHiddenAttribute.
Related
Let's say you have two different libraries that you write for different format of files. One parses type A of file and one parses type B. Now I see that in most cases most folks say that the exceptions already defined (let's say we use C# and .NET) are enough to handle most situations. In this case I think that is OK that in both cases we if we encounter some problems when parsing we throw a InvalidDataException that tells us that the format is not correct.What happens when we must catch both exceptions in a higher level function that must do something with them?
void SomeHigherFunction()
{
try
{
int x = GetSomeDataFromFileA(); // throws InvalidDataException
int y = GetSomeDataFromFileB(); // throws InvalidDataException
}
catch(InvalidDataException) // what failed ?
{
ShowMessageWithWhatFileFailed() // what display ?
}
}
How do we know where the code failed? Should in this case be two different Exception types defined, one TypeAException and one TypeBException or is something easy here that I miss? I don't want to wrap each function and return a bool with the result. In this case I would wrap function A in a function and let it return true if successful and execute B further. But that is clearly a bad design and wrong use of exceptions. Should I just create new types in this cases ? Or how?
You can use Exception.Data Collection to pass the owner of the Exception and do something with it further.
I refactored your example a little, but i think this fits your requirements:
class Program
{
[Serializable]
public abstract class Parser
{
public int GetData()
{
bool error = true;
if (error)
{
InvalidDataException exception = new InvalidDataException();
exception.Data.Add("owner", this);
throw exception;
}
return 0;
}
public abstract void handleError();
}
[Serializable]
private class ParserA : Parser
{
public override void handleError()
{
Console.WriteLine("Handled in A");
}
}
[Serializable]
private class ParserB : Parser
{
public override void handleError()
{
Console.WriteLine("Handled in B");
}
}
static void Main(String[] args)
{
try
{
int x = new ParserA().GetData();
int y = new ParserB().GetData();
}
catch (InvalidDataException ex)
{
Parser parser = ex.Data["owner"] as Parser;
if(parser != null)
parser.handleError();
// or even this if you prefer:
if (parser is ParserA)
Console.WriteLine("A");
}
}
}
In a real case scenario GetData method would be virtual, but you got the idea
This might seem like an odd question but google is not giving me anything to go on.
I have some extension methods that allow me to evaluate return values and so forth on demand. I use them in places where Contracts don't really do what I want.
What these extension methods do is a combination of old school Debug.Assert() and a 'for realsies' check that throws an exception if the conditional is not met. I have others that allow you to throw a specific exception as well. Example:
public static void IsNotNullOrEmpty(this System.Collections.ICollection input, string message = default(string), bool throwOnFailure = true)
{
if (!string.IsNullOrEmpty(message))
Debug.Assert(input != null && input.Count > 0, message);
if (input == null || input.Count == 0 && throwOnFailure)
throw new ArgumentNullException(message);
}
public static void IsNotNull<T>(this object input, string message = default(string), bool throwOnFailure = true) where T : Exception, new()
{
if (!string.IsNullOrEmpty(message))
Debug.Assert(input != null, message);
if (input == null && throwOnFailure)
{
// NOTE - catches the possibility that the Exception class's implementation does not have a constructor that takes a message
// Have to do it this way because the Message property is readonly on the Exception class so we can't just set it.
try
{
throw Activator.CreateInstance(typeof(T), message) as T;
}
catch(MissingMethodException)
{
throw new T();
}
}
}
They actually work really well. The only problem being that the debug assert snaps the debugger onto the Debug.Assert() line. I'd like it to snap on the line that actually violated the constraint.
So my question is, I can easilly use .GetFrame(1) on a stacktrace to get the MethodInfo for the method that called the constraint. But how do I get the debugger in VS to back up one frame and SHOW that method as if you'd double clicked on it in the callstack window?
There may well be a way to do this with some prepackaged thing on Nuget or what have you but these have served me pretty well so far.
Anybody have an idea?
thanks
E
What you want is the DebuggerStepThroughAttribute.
When an exception is thrown in a method tagged with this attribute, the debugger will be placed on the line that called the method, and not inside the method.
In other words, you want to declare your methods like this:
[DebuggerStepThrough]
public static void IsNotNullOrEmpty(...)
{
...
}
[DebuggerStepThrough]
public static void IsNotNull<T>(...)
where T : Exception, new()
{
...
}
Also note that if you use the step into function in the debugger, you will not step into one of these methods but instead step over it as though it was external, which will make debugging these methods harder.
You may want to consider placing that attribute inside #ifdef...#endig section to make it easy to switch to a configuration that allows you to debug them.
I am just wondering if you mean this. This is returning the Name of the Method and Class the program was called from.
public static bool IsNull(this string value)
{
var method = new StackTrace().GetFrame(1).GetMethod();
Console.WriteLine(String.Format("I was called from '{0}' of class '{1}'", method.Name, method.DeclaringType));
return string.IsNullOrEmpty(value);
}
I have an method that throws exception :
public void MyMethod()
{
// do some logging
throw new Exception("My Text");
}
I'm using this method in more than 100 places in my code, the problem is when i use this method in another method that must return a value Re-sharper dose not understands that there is no need for returning a value, for example :
public int AnotherMethod()
{
// some stuff
MyMethod(); // <= it always throws exception
return 0; // i have to put this code, while it never executes
}
is there any way to tell Re-sharper that MyMethod is an exception just like this:
public int AnotherMethod()
{
// some stuff
throw new Exception(); // <= it always throws exception
//return 0; <= this line is no more needed
}
There's two issues here.
First, you can give ReSharper hints to code analysis, and I'll show you how below.
The problem here, however, is not ReSharper, but the compiler. The compiler will not be persuaded by these hints. The method you showed:
public int AnotherMethod()
{
// some stuff
MyMethod(); // <= it always throws exception
return 0; // i have to put this code, while it never executes
}
Will have to be written like this even if you persuade ReSharper to understand that MyMethod always throws an exception. This has nothing to do with ReSharper, this is solely the C# compiler.
In order to tell ReSharper that your method behaves in a certain way, you can tag it with an attribute. You need to either copy a source code copy of those attributes into your project, or reference the ReSharper annotations assembly. Once you've done that, you can tag MyMethod like this:
[ContractAnnotation("=> halt")]
public void MyMethod()
...
However, again, the C# compiler will not care about this and will still complain about the missing return.
You can read more about the various attributes that ReSharper understands here: ReSharper Code Annotations Attributes.
You should not use an exception on a method like this, because exceptions are meant to raise WHEN a method could not achive its goal because of EXCEPTIONAL conditions, not ALWAYS.
You should use a custom exception like
public class MyException():Exception
{
public MyException(): base("Your text goes here")
{
// do some logging
}
}
You could also add properties to your custom exception class, and hold additional information on them like
public class MyException():Exception
{
public long Id { get; set; }
public MyException(long id): base("Your text goes here")
{
this.Id = id;
// and do some logging
}
}
You should create an exception and throw it. Eg
public int AnotherMethod()
{
// some stuff
throw MyMethod(); // now it is obvious it always throws an exception
}
public Exception MyMethod(){
return new Exception("new exception");
}
There are a few different common patterns for returning the result of a function call in public APIs. It is not obvious which is the best approach. Is there a general consensus on a best practice, or, at least convincing reasons why one pattern is better the others?
Update By public API, I mean the public members that are exposed to dependent assemblies. I am not referring exclusively to an API that is exposed publicly as a web service. We can make the assumption that clients are using .NET.
I wrote a sample class below to illustrate the different patterns for returning values, and I have annotated them expressing my concerns for each one.
This is a bit of a long question, but I'm sure I'm not the only person to have considered this and hopefully this question will be interesting to others.
public class PublicApi<T> // I am using the class constraint on T, because
where T: class // I already understand that using out parameters
{ // on ValueTypes is discouraged (http://msdn.microsoft.com/en-us/library/ms182131.aspx)
private readonly Func<object, bool> _validate;
private readonly Func<object, T> _getMethod;
public PublicApi(Func<object,bool> validate, Func<object,T> getMethod)
{
if(validate== null)
{
throw new ArgumentNullException("validate");
}
if(getMethod== null)
{
throw new ArgumentNullException("getMethod");
}
_validate = validate;
_getMethod = getMethod;
}
// This is the most intuitive signature, but it is unclear
// if the function worked as intended, so the caller has to
// validate that the function worked, which can complicates
// the client's code, and possibly cause code repetition if
// the validation occurs from within the API's method call.
// It also may be unclear to the client whether or not this
// method will cause exceptions.
public T Get(object argument)
{
if(_validate(argument))
{
return _getMethod(argument);
}
throw new InvalidOperationException("Invalid argument.");
}
// This fixes some of the problems in the previous method, but
// introduces an out parameter, which can be controversial.
// It also seems to imply that the method will not every throw
// an exception, and I'm not certain in what conditions that
// implication is a good idea.
public bool TryGet(object argument, out T entity)
{
if(_validate(argument))
{
entity = _getMethod(argument);
return true;
}
entity = null;
return false;
}
// This is like the last one, but introduces a second out parameter to make
// any potential exceptions explicit.
public bool TryGet(object argument, out T entity, out Exception exception)
{
try
{
if (_validate(argument))
{
entity = _getMethod(argument);
exception = null;
return true;
}
entity = null;
exception = null; // It doesn't seem appropriate to throw an exception here
return false;
}
catch(Exception ex)
{
entity = null;
exception = ex;
return false;
}
}
// The idea here is the same as the "bool TryGet(object argument, out T entity)"
// method, but because of the Tuple class does not rely on an out parameter.
public Tuple<T,bool> GetTuple(object argument)
{
//equivalent to:
T entity;
bool success = this.TryGet(argument, out entity);
return Tuple.Create(entity, success);
}
// The same as the last but with an explicit exception
public Tuple<T,bool,Exception> GetTupleWithException(object argument)
{
//equivalent to:
T entity;
Exception exception;
bool success = this.TryGet(argument, out entity, out exception);
return Tuple.Create(entity, success, exception);
}
// A pattern I end up using is to have a generic result class
// My concern is that this may be "over-engineering" a simple
// method call. I put the interface and sample implementation below
public IResult<T> GetResult(object argument)
{
//equivalent to:
var tuple = this.GetTupleWithException(argument);
return new ApiResult<T>(tuple.Item1, tuple.Item2, tuple.Item3);
}
}
// the result interface
public interface IResult<T>
{
bool Success { get; }
T ReturnValue { get; }
Exception Exception { get; }
}
// a sample result implementation
public class ApiResult<T> : IResult<T>
{
private readonly bool _success;
private readonly T _returnValue;
private readonly Exception _exception;
public ApiResult(T returnValue, bool success, Exception exception)
{
_returnValue = returnValue;
_success = success;
_exception = exception;
}
public bool Success
{
get { return _success; }
}
public T ReturnValue
{
get { return _returnValue; }
}
public Exception Exception
{
get { return _exception; }
}
}
Get - use this if validation failing is unexpected or if it's feasible for callers to validate the argument themselves before calling the method.
TryGet - use this if validation failing is expected. The TryXXX pattern can be assumed to be familiar due it's common use in the .NET Framework (e.g., Int32.TryParse or Dictonary<TKey, TValue>.TryGetValue).
TryGet with out Exception - an exception likely indicates a bug in the code passed as delegates to the class, because if the argument was invalid then _validate would return false instead of throwing an exception and _getMethod would not be called.
GetTuple, GetTupleWithException - never seen these before. I wouldn't recommend them, because a Tuple isn't self-explaining and thus not a good choice for a public interface.
GetResult - use this if _validate needs to return more information than a simple bool. I wouldn't use it to wrap exceptions (see: TryGet with out Exception).
If by "public API" you mean an API by will be consumed by applications outside of your control and those client apps will written in a variety of languages/platforms I would suggest returning very basic types (e.g. strings, integers, decimals) and use something like JSON for more complex types.
I don't think you can expose a generic class in a public API since you don't know if the client will support generics.
Pattern-wise I would lean towards a REST-like approach rather than SOAP. Martin Fowler has a good article high level article on what this means: http://martinfowler.com/articles/richardsonMaturityModel.html
Things to consider, before answer:
1- There is a special situation about DOTNet programming languages & Java, due that you can easily retrieve objects, instead of only primitive types. Example: so a "plain C" A.P.I. may differ to a C# A.P.I.
2- If there is an error in you A.P.I., while retriving a data, how to handle, without interrumpting you application.
Answer:
A pattern, I have seen in several libraries, its a function, that its main result its an integer, in which 0 means "success", and another integer value means an specific error code.
The function may have several arguments, mostly read-only or input parameters, and a single reference or out parameter that maybe a primitive type a reference to an object, that maybe changed, or a pointer to an object or data structure.
In case of exceptions, some developers, may catch them and generate an specific error code.
public static class MyClass
{
// not recomended:
int static GetParams(ref thisObject, object Param1, object Params, object Param99)
{
const int ERROR_NONE = 0;
try
{
...
}
catch (System.DivideByZeroException dbz)
{
ERROR_NONE = ...;
return ERROR_NONE;
}
catch (AnotherException dbz)
{
ERROR_NONE = ...;
return ERROR_NONE;
}
return ERROR_NONE;
} // method
// recomended:
int static Get(ref thisObject, object ParamsGroup)
{
const int ERROR_NONE = 0;
try
{
...
}
catch (System.DivideByZeroException dbz)
{
ERROR_NONE = ...;
return ERROR_NONE;
}
catch (AnotherException dbz)
{
ErrorCode = ...;
return ERROR_NONE;
}
return ERROR_NONE;
} // method
} // class
Its similar to your tuple result. Cheers.
UPDATE 1: Mention about exception handling.
UPDATE 2: explicit declare constants.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Finding the Variable Name passed to a Function in C#
In C#, is there a way (terser the better) to resolve the name of a parameter at runtime?
For example, in the following method, if you renamed the method parameter, you'd also have to remember to update the string literal passed to ArgumentNullException.
public void Woof(object resource)
{
if (resource == null)
{
throw new ArgumentNullException("resource");
}
// ..
}
One way:
static void Main(string[] args)
{
Console.WriteLine("Name is '{0}'", GetName(new {args}));
Console.ReadLine();
}
This code also requires a supporting function:
static string GetName<T>(T item) where T : class
{
var properties = typeof(T).GetProperties();
Enforce.That(properties.Length == 1);
return properties[0].Name;
}
Basically the code works by defining a new Anonymous Type with a single Property consisting of the parameter who's name you want. GetName() then uses reflection to extract the name of that Property.
There are more details here: http://abdullin.com/journal/2008/12/13/how-to-find-out-variable-or-parameter-name-in-c.html
Short answer: No, there isn't. (Is that terse enough? ;)
(EDIT: Justin's answer probably counts. It leaves a bad taste in my mouth, but it accomplishes the goal of "no need to put the parameter name into a string". I don't think I'd really count AOP though, as that's really changing to a completely different approach rather than answering the original question of getting a parameter name from within a method.)
Longer answer: There's a way to find out all the parameters of a method, but I don't think it's useful in this case.
Here's an example which displays the parameter names from a couple of methods:
using System;
using System.Reflection;
class Test
{
static void Main()
{
Foo(null);
Bar(null);
}
static void Foo(object resource)
{
PrintParameters(MethodBase.GetCurrentMethod());
}
static void Bar(object other)
{
PrintParameters(MethodBase.GetCurrentMethod());
}
static void PrintParameters(MethodBase method)
{
Console.WriteLine("{0}:", method.Name);
foreach (ParameterInfo parameter in method.GetParameters())
{
Console.WriteLine(" {0} {1}",
parameter.ParameterType,
parameter.Name);
}
}
}
So that does that, but if you have multiple parameters and you wanted to throw an appropriate exception, how would you know (in a safe way) which to use? Ideally you want something like:
public void Woof(object resource)
{
if (resource == null)
{
throw new ArgumentNullException(infoof(resource));
}
// ..
}
where the mythical infoof operator would return a ParameterInfo. Unfortunately this doesn't exist.
I dealt with this very same issue. There are a couple of ways of getting the parameter name but the most performant is to dip down into the IL. You can see an example of my implementation on my blog post on this very issue Taking the pain out of parameter validation.
The one caveat to this approach is you need to pass the parameter name in as a delegate but it is small price to pay for cleaner code:
public void SomeMethod(string value)
{
Validate.Argument(() => value).IsNotNull().IsNotEmpty();
}
Which is somewhat cleaner and clearer than:
public void SomeMethod(string value)
{
if (value == null)
{
throw new ArgumentNullException("value");
}
if (value == string.Empty)
{
throw new ArgumentException("Value cannot be an empty string.", "value");
}
}
The static method approach has allowed me to chain a number of methods together in a fluent interface. Initially an Argument object is returned which only allows a basic null test which returns a ReferenceArgument object which can then have additional validation. If the object under test is a value type then different tests are available.
The API allows for a number of common tests but it would be hard to capture all the possible tests so to provide flexibility a generic test method allows an expression or function to be provided and in the case of the former the expression can actually be used as the error message.
My example only covers a few of the basics but you can easily expand the interface to check for ranges and throw ArgumentOutOfRangeExceptions or test objects inherit from a specific base class or implement an interface. There are some similar implementations but I have not as yet seen any that get the parameter name.
You can get this information using AOP. You can define an intercept that is invoked before method execution and throw the exception there. This also takes care of the problem that null checking is a cross-cutting concern.
PostSharp is a good simple implementation of AOP.
Here's what your code would look like (haven't tested, but it should get you very close)
[AttributeUsage(AttributeTargets.Parameter)]
public class CanBeNullAttribute : Attribute
{
private readonly bool canBeNull;
public CanBeNullAttribute()
: this(true)
{
}
public CanBeNullAttribute(bool canBeNull)
{
this.canBeNull = canBeNull;
}
public bool AllowNull
{
get { return canBeNull; }
}
}
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class EnforceNullConstraintAttribute : OnMethodInvocationAspect
{
public override void OnInvocation(MethodInvocationEventArgs eventArgs)
{
object[] arguments = eventArgs.GetArgumentArray();
ParameterInfo[] parameters = eventArgs.Delegate.Method.GetParameters();
for (int i = 0; i < arguments.Length; i++)
{
if (arguments[i] != null) continue;
foreach (CanBeNullAttribute attribute in parameters[i].GetCustomAttributes(typeof(CanBeNullAttribute), true))
{
if (!attribute.AllowNull) throw new ArgumentNullException(parameters[i].Name);
}
}
base.OnInvocation(eventArgs);
}
}
Now, you can modify your method:
[EnforceNullConstraint]
public void Woof([CanBeNull(false)] object resource)
{
// no need to check for null, PostSharp will weave it at compile time
// execute logic assured that "resource" is not null
}
You might want:
1)
public static void ThrowIfNull<T>(Expression<Func<T>> expr)
{
if (expr == null || expr.Compile()() != null) //the compile part is slow
return;
throw new ArgumentNullException(((MemberExpression)expr.Body).Member.Name);
}
or
2)
public static void ThrowIfNull<T>(Expression<Func<T>> expr)
{
if (expr == null)
return;
var param = (MemberExpression)expr.Body;
if (((FieldInfo)param.Member).GetValue(((ConstantExpression)param.Expression).Value) == null)
throw new ArgumentNullException(param.Member.Name);
}
And call it:
Class.ThrowIfNull(() => resource);
But that's not what you would want probably. Its also a lot slower 1) is abt 1000 times slower than 2). May be:
3)
public static void ThrowIfNull<T>(this T item) where T : class
{
if (item == null)
return;
var param = typeof(T).GetProperties()[0];
if (param.GetValue(item, null) == null)
throw new ArgumentNullException(param.Name);
}
And call it:
new { resource }.ThrowIfNull();
Cleaner, much faster than above 2! :)
You can also extend these methods for properties of objects. For eg.,
new { myClass.MyProperty1 }.ThrowIfNull();
You can cache property values to improve performance further as property names don't change during runtime. See related question Finding the variable name passed to a function