Related
In C# 7.1 the below is valid code:
object o = new object();
switch (o)
{
case CustomerRequestBase c:
//do something
break;
}
However, I want to use the pattern switch statement in the following scenario:
public T Process<T>(object message, IMessageFormatter messageFormatter)
where T : class, IStandardMessageModel, new()
{
switch (T)
{
case CustomerRequestBase c:
//do something
break;
}
}
The IDE gives me the error "'T' is a type, which is not valid in the given context"
Is there an elegant way to switch on the type of a generic parameter? I get that in my first example you are switching on the object and the second I'd want to switch on the type T. What would be the best approach to do this?
Below are two different classes called Foo and Bar. You can use one instance of any of these classes as a parameter to a function named Process. After all, you can perform pattern matching as shown in the example function. There is a function named Test for the usage example..
public class Foo
{
public string FooMsg { get; set; }
}
public class Bar
{
public string BarMsg { get; set; }
}
public class Example
{
public T Process<T>(T procClass) where T : class
{
switch (typeof(T))
{
case
var cls when cls == typeof(Foo):
{
var temp = (Foo)((object)procClass);
temp.FooMsg = "This is a Foo!";
break;
}
case
var cls when cls == typeof(Bar):
{
var temp = (Bar)((object)procClass);
temp.BarMsg = "This is a Bar!";
break;
}
}
return
procClass;
}
public void Test(string message)
{
Process(new Foo() { FooMsg = message });
Process(new Bar() { BarMsg = message });
}
}
I agree that there are situation when this approach is faster and not so ugly, and also agree that in any case a better solution should be found, but sometimes the trade-off doesn't pay... so here is a solution (C# 9.0)
return typeof(T) switch
{
Type t when t == typeof(CustomerRequestBase) => /*do something*/ ,
_ => throw new Exception("Nothing to do")
};
I'm going to preface by saying that in general I agree with all the commenters that say switching on a generic T is probably not a good idea. In this case I would advice him to stick with identifying the object, casting it, and then passing it to an appropriate handler.
However, I've been writing a custom binary serializer that needs to be fairly efficient and I've discover one case where I feel the kind of switching (or if statement) he's asking for is justified, so here's how I managed it.
public T ProcessAs<T>(parameters)
{
if (typeof(T) == typeof(your_type_here)
{
your_type_here tmp = process(parameters);
return Unsafe.As<your_type_here, T>(ref tmp);
}
else if (typeof(T) == typeof(your_other_type))
{
your_other_type tmp = otherProcess(parameters);
return Unsafe.As<your_other_type, T>(ref tmp);
}
else
{
throw new ArgumentException(appropriate_msg);
}
}
Note that Unsafe.As<T>(T value) can be used if you're dealing with a class instead of a struct.
If we ignore the codesmell discussion as per comments, an easy readable implementation (hack) can look like this:
public T Process<T>(string number)
{
switch (typeof(T).FullName)
{
case "System.Int32":
return (dynamic) int.Parse(number);
case "System.Double":
return (dynamic) double.Parse(number);
default:
throw new ArgumentException($"{typeof(T).FullName} is not supported");
}
}
Even if you are # with your generic constraints, this is probably bound to cause issues unless you are the sole programmer ;)
Right now we have a set of so called 'services' - classes, that have methods with common signature: their result type have a property T? Error, where T is enum.
And we have a separate enum for each method with a set of values defined for specific method.
This works rather good as long as the final place where we use these services' methods from is controllers' actions — these errors are returned to client, where they are handled by javascript.
But sometime we want to compose some methods of calls of other services' methods, and it is the place where I seem to have a problem.
Let's say we have service's method A(), that has error of type AError. And this A() method calls internally method B() that has an error of type BError.
First of all, we have to map possible BError to AError.
And also it is possible to forget to inspect B's error, and its presence will remain unobserved.
Of cource I know that it is common to use exceptions to indicate that a method has failed.
Right now all controllers have a filter that intercepts unhandled exceptions and returns an answer with just single property Error with value 'InternalServerError'.
But if we start to use exceptions we will loose one feature that I consider important: now a possible set of method's errors is explicitly specified in its signature, and this will be lost in case of we use exceptions.
I know that there is a tag in xml-documentation to list exception types, but it is only documentation, it is not checked by a compiler.
Also I do not understand how to use exceptions on our code:
Let's say we have some method that first checks order's status. Right now it returns 'InvalidOrderStatus' error if order's status is invalid for current action.
If we use exceptions, we can create an exception InvalidOrderStatusException, but how can we know that code that we call internally throws it?
We can also create a mnemonic rule: method A should have error type AError, and inside it should throw some generic exception (let's say, ErrorException<>), parametrized by this AError. And we can intercept this generic exception ErrorException<AError> in all A's calls and observe its error code. But this will not be checked by a compiler: Method A can throw any other exception, or ErrorException<>, but parametrized by some other error code.
So my question is: what is the best way to a) always know what kind of exceptions method can throw and what kind of errors it can return, and b) not be able to forget to observe method's result error?
How about exchanging enum AError with something like this:
class ErrorHolder<T> // T would be AError, BError
{
T ErrorCode {get;}
object[] InnerErrors {get;}
// other payload could go here like inner exceptions etc.
}
Thus you have the enumerated error codes which can be somehow checked plus you can add whatever payload you need.
Create some base exception with desired behaviuor, provide base mechanizm for it's handling, processing and conversion to a result that's being sent to javascript. It doesn't mean that you need to know a list of all possbile exceptions of your method (probaly such list will always be a lie because of possbile non-business exceptions). So derived exceptions can be just a substitutions for error codes, containing specific messages and other data (error code :) ). As you say - "a possible set of method's errors is explicitly specified in its signature" imho it's not an important feature. You should be "object oriented" think of general exception handling (at controller method code level like HandleError(ExecuteService()) or at action filter level). Also, you error codes can be appear not an exceptions but some "execution results" with success or fail status, it's not an exceptional behaviour like "entity not found" but an expected result from service. In this case I use the following code
public class ExecutionResult
{
public ExecutionResult() : this(null)
{
}
public ExecutionResult(ExecutionResult result)
{
if (result != null)
{
Success = result.Success;
Errors = new List<ErrorInfo>(result.Errors);
}
else
{
Errors = new List<ErrorInfo>();
}
}
private bool? _success;
public bool Success
{
get { return _success ?? Errors.Count == 0; }
set { _success = value; }
}
public IList<ErrorInfo> Errors { get; private set; }
}
/*T is for result (any business object)*/
public class ExecutionResult<T> : ExecutionResult
{
public ExecutionResult() : this(null)
{
}
public ExecutionResult(T result) : this(null)
{
Value = result;
}
public ExecutionResult(ExecutionResult result)
: base(result)
{
var r = result as ExecutionResult<T>;
if (r != null)
{
Value = r.Value;
}
}
public T Value { get; set; }
}
So my question is: what is the best way to a) always know what kind of
exceptions method can throw and what kind of errors it can return, and
b) not be able to forget to observe method's result error?
To address "a":
It's hard to do this at compile time. But you can do it via reflection at runtime. See the static enumValues field in the ErrorHandlerFor<T> class.
To address "b", you could do it like this:
In brief: instead of a switch after the call, you prepare error handlers (formerly in the case parts) as lambdas and put all of them in a ErrorHandlerFor<T> class and pass this to the function. This adds the additional benefit of giving feedback to the function whether to continue or abort.
You can also think of this like this:
Assume you want to give some work to a fellow. This work can fail in several ways.
Traditionally you gave the fellow the work and waited till it was finished, maybe with errors. You then handled the errors if necessary.
Now you give the fellow also some "phone numbers" to call when certain errors arise. The answer to the call may even guide the fellow if the work can be continued or needs to be aborted.
enum AError
{
AError1,
AError2,
AError3,
AError4,
AError5,
}
delegate bool SingleErrorHandlerDelegate<T>(T error, object someOtherPayload);
interface IHandle<T>
{
bool Handle(T error, object someOtherPayload); // return true if handled;
}
class ErrorHandlerFor<T> : IHandle<T>
{
private Dictionary<T, SingleErrorHandlerDelegate<T>> handlers;
private static T[] enumValues = Enum.GetValues(typeof(T)).Cast<T>().ToArray();
public ErrorHandlerFor(IEnumerable<KeyValuePair<IEnumerable<T>, SingleErrorHandlerDelegate<T>>> handlers)
: this(handlers.SelectMany(h => h.Key.Select(key => new KeyValuePair<T, SingleErrorHandlerDelegate<T>>(key, h.Value))))
{
}
public ErrorHandlerFor(IEnumerable<KeyValuePair<IEnumerable<T>, SingleErrorHandlerDelegate<T>>> handlers, SingleErrorHandlerDelegate<T> fallbackHandler)
: this(handlers.SelectMany(h => h.Key.Select(key => new KeyValuePair<T, SingleErrorHandlerDelegate<T>>(key, h.Value))), fallbackHandler)
{
}
public ErrorHandlerFor(IEnumerable<KeyValuePair<T, SingleErrorHandlerDelegate<T>>> handlers)
{
this.handlers = new Dictionary<T, SingleErrorHandlerDelegate<T>>();
foreach (var handler in handlers)
{
Debug.Assert(handler.Value != null);
this.handlers.Add(handler.Key, handler.Value);
}
checkHandlers();
}
public ErrorHandlerFor(IEnumerable<KeyValuePair<T, SingleErrorHandlerDelegate<T>>> handlers, SingleErrorHandlerDelegate<T> fallbackHandler)
{
this.handlers = new Dictionary<T, SingleErrorHandlerDelegate<T>>();
foreach (var handler in handlers)
{
Debug.Assert(handler.Value != null);
this.handlers.Add(handler.Key, handler.Value);
}
foreach (var enumValue in enumValues)
{
if (this.handlers.ContainsKey(enumValue) == false)
{
this.handlers.Add(enumValue, fallbackHandler);
}
}
checkHandlers();
}
private void checkHandlers()
{
foreach (var enumValue in enumValues)
{
Debug.Assert(handlers.ContainsKey(enumValue));
}
}
public bool Handle(T error, object someOtherPayload)
{
return handlers[error](error: error, someOtherPayload: someOtherPayload);
}
}
class Test
{
public static void test()
{
var handler = new ErrorHandlerFor<AError>(
new[]{
new KeyValuePair<IEnumerable<AError>, SingleErrorHandlerDelegate<AError>>(
new []{AError.AError1, AError.AError2, AError.AError4,},
(AError error, object payload) => { Console.WriteLine(#"handled error 1, 2 or 4!"); return true;}
),
new KeyValuePair<IEnumerable<AError>, SingleErrorHandlerDelegate<AError>>(
new []{AError.AError3, AError.AError5,},
(AError error, object payload) => { Console.WriteLine(#"could not handle error 3 or 5!"); return false;}
),
}
);
var result = Services.foo(handler);
var incompleteHandlerButWithFallbackThatWillPassTheTest = new ErrorHandlerFor<AError>(
new[]{
new KeyValuePair<IEnumerable<AError>, SingleErrorHandlerDelegate<AError>>(
new []{AError.AError1, AError.AError2, AError.AError4,},
(AError error, object payload) => { Console.WriteLine(#"handled error 1, 2 or 4!"); return true;}
),
new KeyValuePair<IEnumerable<AError>, SingleErrorHandlerDelegate<AError>>(
new []{AError.AError5},
(AError error, object payload) => { Console.WriteLine(#"could not handle error 3 or 5!"); return false;}
),
}
// AError.AError3 is not handled! => will go in fallback
, (AError error, object payload) => { Console.WriteLine(#"could not handle error in fallback!"); return false; }
);
var result2 = Services.foo(incompleteHandlerButWithFallbackThatWillPassTheTest);
var incompleteHandlerThatWillBeDetectedUponInstantiation = new ErrorHandlerFor<AError>(
new[]{
new KeyValuePair<IEnumerable<AError>, SingleErrorHandlerDelegate<AError>>(
new []{AError.AError1, AError.AError2, AError.AError4,},
(AError error, object payload) => { Console.WriteLine(#"handled error 1, 2 or 4!"); return true;}
),
new KeyValuePair<IEnumerable<AError>, SingleErrorHandlerDelegate<AError>>(
new []{AError.AError3},
(AError error, object payload) => { Console.WriteLine(#"could not handle error 3 or 5!"); return false;}
),
} // AError.AError5 is not handled! => will trigger the assertion!
);
}
}
class Services
{
public static Result foo(IHandle<AError> errorHandler)
{
Debug.Assert(errorHandler != null);
// raise error...
var myError = AError.AError1;
var handled = errorHandler.Handle(error: myError, someOtherPayload: "hello");
if (!handled)
return new Result();
// maybe proceed
var myOtherError = AError.AError3;
errorHandler.Handle(error: myOtherError, someOtherPayload: 42); //we'll return anyway in this case...
return new Result();
}
public class Result
{
}
}
What is the defined behaviour in C# for when an exception is thrown before setting the value of an out parameter, and you then try to access the parameter?
public void DoSomething(int id, out control)
{
try
{
int results = Call(Id);
control = new CallControl(results);
}
catch(Exception e)
{
throw new Exception("Call failed", e);
}
}
//somewhere else
DoSomething(out Control control)
{
try
{
DoSomething(1, out control);
}
catch()
{
// handle exception
}
}
// later
Control control;
DoSomething(out control)
control.Show();
The compiler normally complains about exiting the method before setting the out parameter. This seems to outsmart it from protecting me from myself.
What is the defined behaviour in C# for when an exception is thrown before setting the value of an out parameter, and you then try to access the parameter?
You can't do so. The variable will still not be definitely assigned, unless it's definitely assigned before the method call.
If the variable was definitely assigned before the method call, then it will still be definitely assigned - but unless the method assigned a value before the exception was thrown, the variable's value will remain untouched:
class Test
{
static void JustThrow(out int x)
{
throw new Exception();
}
static void Main()
{
int y = 10;
try
{
JustThrow(out y);
}
catch
{
// Ignore
}
Console.WriteLine(y); // Still prints 10
}
}
That's OK. If DoSomething throws, control.Show() is not executed.
You can't outsmart the compiler anyway, because it knows when the control flow could bypass the initialisation.
Consider this code, which is similar to the code you were proposing:
using System;
namespace Demo
{
internal class Program
{
private void run()
{
int a;
try
{
DoSomething(out a);
}
catch {} // Evil empty catch.
Console.WriteLine(a); // Compile error.
}
public void DoSomething(out int x)
{
test();
x = 0;
}
private static void test()
{
throw new InvalidOperationException("X");
}
private static void Main()
{
new Program().run();
}
}
}
It gives a compile error because you have put a try/catch around the DoSomething() and therefore the compiler assumes that a might not have been initialised.
(Note that all stack variables are initialised to their default values if you don't initialise them explicitly, but that doesn't affect the compiler's control flow analysis. The compiler cares about definite assignment, not the default initialisation that the CLR does. This initialisation is not guaranteed by the C# standard anyway.)
If you change the empty catch to one that throws, the compile error goes away:
catch { throw new Exception("Test"); } // Compile error goes away.
because now you can't reach the code that uses a if an exception occurred.
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.
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.