I'm working with some classes which, when throwing, have a relatively deep InnerException tree. I'd like to log and act upon the innermost exception which is the one having the real reason for the problem.
I'm currently using something similar to
public static Exception getInnermostException(Exception e) {
while (e.InnerException != null) {
e = e.InnerException;
}
return e;
}
Is this the proper way to handle Exception trees?
I think you can get the innermost exception using the following code:
public static Exception getInnermostException(Exception e) {
return e.GetBaseException();
}
You could use the GetBaseException method.
Very quick example:
try
{
try
{
throw new ArgumentException("Innermost exception");
}
catch (Exception ex)
{
throw new Exception("Wrapper 1",ex);
}
}
catch (Exception ex)
{
// Writes out the ArgumentException details
Console.WriteLine(ex.GetBaseException().ToString());
}
In a word, yes. I cannot think of any significantly better or different way of doing it. Unless you wanted to add it as an extension method instead, but it's really six of one, half-a-dozen of the other.
There are exceptions that can have multiple root causes (e.g. AggregateException and ReflectionTypeLoadException).
I created my own class to navigate the tree and then different visitors to either collect everything or just the root causes. Sample outputs here. Relevant code snippet below.
public void Accept(ExceptionVisitor visitor)
{
Read(this.exception, visitor);
}
private static void Read(Exception ex, ExceptionVisitor visitor)
{
bool isRoot = ex.InnerException == null;
if (isRoot)
{
visitor.VisitRootCause(ex);
}
visitor.Visit(ex);
visitor.Depth++;
bool isAggregateException = TestComplexExceptionType<AggregateException>(ex, visitor, aggregateException => aggregateException.InnerExceptions);
TestComplexExceptionType<ReflectionTypeLoadException>(ex, visitor, reflectionTypeLoadException => reflectionTypeLoadException.LoaderExceptions);
// aggregate exceptions populate the first element from InnerExceptions, so no need to revisit
if (!isRoot && !isAggregateException)
{
visitor.VisitInnerException(ex.InnerException);
Read(ex.InnerException, visitor);
}
// set the depth back to current context
visitor.Depth--;
}
private static bool TestComplexExceptionType<T>(Exception ex, ExceptionVisitor visitor, Func<T, IEnumerable<Exception>> siblingEnumerator) where T : Exception
{
var complexException = ex as T;
if (complexException == null)
{
return false;
}
visitor.VisitComplexException(ex);
foreach (Exception sibling in siblingEnumerator.Invoke(complexException))
{
visitor.VisitSiblingInnerException(sibling);
Read(sibling, visitor);
}
return true;
}
Related
This question already has answers here:
Is there a way to catch all unhandled exceptions thrown by a given class?
(6 answers)
Closed 8 years ago.
I have a lot of classes (WCF services) that contain several function. Now I need to handle errors, but I don't want to create a block try ... catch within each function (for error handling).
How can I make try...catch in any class (or something else) so that we catch errors but did not write the same block within each method?
There will always be some duplication of code but you can reduce it to one line
public static class ExceptionHandler
{
public static void Run(Action action)
{
try
{
a();
}
catch(Exception e)
{
//Do Something with your exception here, like logging
}
}
}
and then just call
ExceptionHandler.Run(yourAction);
you can add overloads for functions and what not but this approach is not ideal. As you may want to catch specific exceptions in certain cases.
Since you did not provide code specifically, I will write some sample code to make it more obvious. If you have this:
public class MyClass
{
public void Method1ThatCanThrowException()
{
try
{
// the Method1 code that can throw exception
}
catch (MySpecificException ex)
{
// some specific error handling
}
}
public object Method2ThatCanThrowException()
{
try
{
// the Method2 code that can throw exception
}
catch (MySpecificException ex)
{
// the same specific error handling
}
}
}
So, if you intend to have single place error handling, you can use lambda, and the help of a private method:
private T CheckAndCall<T>(Func<T> funcToCheck)
{
try
{
return funcToCheck();
}
catch (MySpecificException ex)
{
// the old specific error handling
}
}
Notice the use of the Func<T> delegate. This is because you may need to wrap the try-catch logic around some code that can return a value.
Then you can rewrite the above methods like this:
public void Method1ThatCanThrowException()
{
CheckAndCall(
() =>
{
// the Method1 code that can throw exception
return null;
});
}
public object Method2ThatCanThrowException()
{
return CheckAndCall(
() =>
{
// the Method2 code that can throw exception
return someObject;
});
}
For example, rather than having to do this:
public class Program
{
public static string ReadFile(string filename)
{
//A BCL method that throws various exceptions
return System.IO.File.ReadAllText(filename);
}
public static void Main(string[] args)
{
try
{
Console.Write(ReadFile("name.txt"));
}
catch (Exception e)
{
Console.WriteLine("An error occured when retrieving the name! {0}", e.Message);
}
try
{
Console.Write(ReadFile("age.txt"));
}
catch (Exception e)
{
Console.WriteLine("An error occured when retrieving the age! {0}", e.Message);
}
}
}
You could implement a "Try..." method, using the ref or out keyword as appropriate:
public class Program
{
public static bool TryReadFile(string filename, out string val)
{
try
{
val = System.IO.File.ReadAllText(filename);
return true;
}
catch (Exception)
{
return false;
}
}
public static void Main(string[] args)
{
string name, age;
Console.WriteLine(TryReadFile("name.txt", out name) ? name : "An error occured when retrieving the name!");
Console.WriteLine(TryReadFile("age.txt", out age) ? age: "An error occured when retrieving the age!");
}
}
The downside to this approach is that you can't act upon a specific exception, but in the case of simply determining if an operation has or has not succeeded, I find this to be a syntactically clean approach.
Related
Related
I want to dynamically invoke a MethodInfo object and have any exceptions that get thrown from inside of it pass outward as if it were called normally.
I have two options it seems. They're outlined below.
Option 1 maintains the type of the exception thrown by MyStaticFunction, but the StackTrace is ruined because of the throw.
Option 2 maintains the StackTrace of the exception, but the type of the exception is always TargetInvocationException. I can pull out the InnerException and its type, but that means that I can't write this for example:
try { DoDynamicCall(); }
catch (MySpecialException e) { /* special handling */ }
Option 1:
void DoDynamicCall()
{
MethodInfo method = /*referencing MyClass method void MyStaticFunction(int x)*/;
try
{
method.Invoke(null, new object[] { 5 });
}
catch (TargetInvocationException e)
{
throw e.InnerException;
}
}
Option 2:
void DoDynamicCall()
{
MethodInfo method = /*referencing MyClass method void MyStaticFunction(int x)*/;
method.Invoke(null, new object[] { 5 });
}
What I really want is for callers to DoDynamicCall to receive exceptions as if they had called this:
void DoDynamicCall()
{
MyClass.MyStaticFunction(5);
}
Is there a way to get the benefits of both Option 1 and Option 2?
Edit:
The option I wish I had (invented special new C# keyword rethrow on the spot):
void DoDynamicCall()
{
MethodInfo method = /*referencing MyClass method void MyStaticFunction(int x)*/;
try
{
method.Invoke(null, new object[] { 5 });
}
catch (TargetInvocationException e)
{
//Magic "rethrow" keyword passes this exception
//onward unchanged, rather than "throw" which
//modifies the StackTrace, among other things
rethrow e.InnerException;
}
}
This would also eliminate the need for this weirdo, because you could use rethrow e; instead:
try { ... }
catch (Exception e)
{
if (...)
throw;
}
In general, it would be a way to decouple throw; from the requirement "I have to be directly in a catch block."
Here's the solution I came up with. It gets the job done. I'm still interested in other answers as there might be something easier or cleaner.
When you want the functionality of throw; but the exception you want to pass on is not the exception of the current catch block, use throw Functional.Rethrow(e);
Replace try...catch... with Functional.TryCatch
Replace try...catch...finally... with Functional.TryCatchFinally
Here's the code:
//Need a dummy type that is throwable and can hold an Exception
public sealed class RethrowException : Exception
{
public RethrowException(Exception inner) : base(null, inner) { }
}
public static Functional
{
public static Exception Rethrow(Exception e)
{
return new RethrowException(e);
}
public static void TryCatch(Action _try, Action<Exception> _catch)
{
try { _try(); }
catch (RethrowException e) { _catch(e.InnerException); }
catch (Exception e) { _catch(e); }
}
public static T TryCatch<T>(Func<T> _try, Func<Exception, T> _catch)
{
try { return _try(); }
catch (RethrowException e) { return _catch(e.InnerException); }
catch (Exception e) { return _catch(e); }
}
public static void TryCatchFinally(
Action _try, Action<Exception> _catch, Action _finally)
{
try { _try(); }
catch (RethrowException e) { _catch(e.InnerException); }
catch (Exception e) { _catch(e); }
finally { _finally(); }
}
public static T TryCatchFinally<T>(
Func<T> _try, Func<Exception, T> _catch, Action _finally)
{
try { return _try(); }
catch (RethrowException e) { return _catch(e.InnerException); }
catch (Exception e) { return _catch(e); }
finally { _finally(); }
}
}
Update
In .NET 4.5 there is the new System.Runtime.ExceptionServices.ExceptionDispatchInfo class. This can be used to capture an exception:
var capturedException = ExceptionDispatchInfo.Capture(e);
And then later this is used to resume throwing the exception:
capturedException.Throw();
No, I don't believe there is a way to have the benefits of both. However, throwing e.InnerException will still allow you to get the original stacktrace, because you can simply use e.InnerException.StackTrace to get the original stack trace. So, in short, you should use option 1.
The best option is Option 3: don't use reflection at all, but instead use Expression<T>.Compile().
Instead of doing this:
static void CallMethodWithReflection(MethodInfo method)
{
try
{
method.Invoke(null, new object[0]);
}
catch (TargetInvocationException exp)
{
throw exp.InnerException;
}
}
Try to aim for this:
private static void CallMethodWithExpressionCompile(MethodInfo method)
{
Expression.Lambda<Action>(Expression.Call(method)).Compile()();
}
The caveat is that you need to know the method signature, although you can write code that dynamically builds the expression to fit one of several signatures.
You may not always be able to use this technique, but when you do it is the best option. For all intents and purposes it is like calling any other delegate. It is also faster than reflection if you make multiple calls (in this case compile only once and keep a handle on the compiled delegate).
I had a similar issue and came up with this:
/// <summary>
/// Attempts to throw the inner exception of the TargetInvocationException
/// </summary>
/// <param name="ex"></param>
[DebuggerHidden]
private static void ThrowInnerException(TargetInvocationException ex)
{
if (ex.InnerException == null) { throw new NullReferenceException("TargetInvocationException did not contain an InnerException", ex); }
Exception exception = null;
try
{
//Assume typed Exception has "new (String message, Exception innerException)" signature
exception = (Exception) Activator.CreateInstance(ex.InnerException.GetType(), ex.InnerException.Message, ex.InnerException);
}
catch
{
//Constructor doesn't have the right constructor, eat the error and throw the inner exception below
}
if (exception == null ||
exception.InnerException == null ||
ex.InnerException.Message != exception.Message)
{
// Wasn't able to correctly create the new Exception. Fall back to just throwing the inner exception
throw ex.InnerException;
}
throw exception;
}
An Example of it's use is below:
try
{
return typeof(MyType).GetMethod(methodName, BindingFlags.Public | BindingFlags.Static)
.MakeGenericMethod(new[] { myType) })
.Invoke(null, parameters);
}
catch (TargetInvocationException ex)
{
ThrowInnerException(ex);
throw new Exception("Throw InnerException didn't throw exception");
}
Is it possible to somehow invoke inline try statement in C#?
I'm detecting languages for my website and sometimes, when language is something like en-GR on client side for some reason .NET throws exception. So I need to use try and also catch even though I'm not really catching anything.
It just seems as a total overkill in this situation.
// Set allowed languages
string[] allowedLanguages = { "en", "fr", "ru" };
// Get all possible values
var routeLanguage = (filterContext.RouteData.Values["lang"] != null && allowedLanguages.Contains(filterContext.RouteData.Values["lang"].ToString())) ? filterContext.RouteData.Values["lang"].ToString() : null;
var cookieLanguage = (filterContext.HttpContext.Request.Cookies["lang"] != null && allowedLanguages.Contains(filterContext.HttpContext.Request.Cookies["lang"].Value)) ? filterContext.HttpContext.Request.Cookies["lang"].Value : null;
string clientLanguage = null;
try
{
clientLanguage = (filterContext.HttpContext.Request.UserLanguages != null) ? new CultureInfo(filterContext.HttpContext.Request.UserLanguages[0]).TwoLetterISOLanguageName : null; // Exception sometimes without `try`
}
catch (Exception)
{
}
Edit
Exception is not something I can fix since I have no control over what user has in his culture info. .NET just sees en-FR as invalid one.
First off, it is always better to figure out how to avoid the exception in the first place. Concentrate on that first. There is some reason why that exception is being thrown, and if you can determine what it is, then don't do that.
To actually answer your question: there is no out-of-the-box "eat all the exceptions in this expression" mechanism, but building your own is straightforward:
static T EatExceptions(Func<T> func)
{
try { return func(); } catch { }
return default(T);
}
...
clientLanguage = (filterContext.HttpContext.Request.UserLanguages != null) ?
EatExceptions(() => new CultureInfo(filterContext.HttpContext.Request.UserLanguages[0]).TwoLetterISOLanguageName) :
null; }
If someone tried to pull shenanigans like that in code I was reviewing then I would... well let's just say that the change would not get checked in. Eating exceptions like this is a very bad idea 99% of the time. Again: figure out what you are doing wrong and stop doing it. Don't do something wrong and then handle the failure.
Have you tried getting rid of the try/catch statement completely?
string clientLanguage = null;
var userLanguages = filterContext.HttpContext.Request.UserLanguages;
if (userLanguages != null && userLanguages.Length > 0)
{
var culture = CultureInfo
.GetCultures(CultureTypes.AllCultures)
.FirstOrDefault(
x => string.Equals(
x.Name,
userLanguages[0].Name,
StringComparison.OrdinalIgnoreCase
)
);
if (culture != null)
{
clientLanguage = culture.TwoLetterISOLanguageName;
}
}
Use try/catch only for handling exceptions that are out of your control. As their name suggests exceptions should be used for handling exceptional cases.
In this case you are doing standard parsing so it is much better to do defensive programming instead of trying, throwing, catching, ...
_.Try(() => __YourStatementHere__ );
Using a little helper class like this:
/// <summary>
/// Other utility functions.
/// </summary>
public static class _ {
/// <summary>
/// Tries to execute the given action. If it fails, nothing happens.
/// </summary>
public static void Try(Action action) {
try {
action();
}
catch {
}
}
}
I know, this solution is not optimal either, but up to now the most concise one I could find.
First try to avoid the exception. Just because the string comes from a source you don't control, doesn't mean you can't validate it.
If you can't avoid it, you should catch the specific exception you expect and encapsulate that logic in a method. Don't catch all exceptions.
For example:
public static CultureInfo TryGetCultureByName(string name)
{
try
{
return new CultureInfo(name);
}
catch(CultureNotFoundException)//Only catching CultureNotFoundException
{
return null;
}
}
That way, if you later discover a better way to handle this specific error, you can easily replace it.
For example you could create a Dictionary<string, CultureInfo>, fill it from CultureInfo.GetCultures() and use TryGetValue to look up a culture without ever throwing an exception.
What you did is the right way to do it. You stated, why you cannot get rid of the exception (and I assume this is the case). So you have to handle it. Alas, C# does not have a try-catch as an expression (not sure how that would work - the catch "clause" would need to return a value).
Alternatively you can build a little helper function that takes a Func<T>, invokes it and passes through the value to the caller. If an exception occurres it returns (for example) default(T). That takes away a lot of the clutter and is reusable.
Well, leaving aside the (good) advice about pre-checking, there are several rather mundane/prosaic/obvious ways to do this:
First, you could wrap it in a function. I assume that this would not be general enough for you.
Or, you could collapse the catch branch:
try
{
clientLanguage = (filterContext.HttpContext.Request.UserLanguages != null) ? new CultureInfo(filterContext.HttpContext.Request.UserLanguages[0]).TwoLetterISOLanguageName : null; // Exception sometimes without `try`
} catch (Exception) { }
Or, you could just collapse the whole thing to a single line:
try { clientLanguage = (filterContext.HttpContext.Request.UserLanguages != null) ? new CultureInfo(filterContext.HttpContext.Request.UserLanguages[0]).TwoLetterISOLanguageName : null; } catch (Exception) { }
Not elegant, but simple, and it works.
This is one another way:
await new #try(async () => { user = await GetItemAsync(userId); })
.#catch<Exception>(async () => { user = new User(); });
I think it's more verbose than the try/catch:
try { return await GetItemAsync(userId); }
catch (Exception ex) { return new User(); }
The helper class:
public class #try
{
private Func<Task> func;
private Action action;
public #try(Func<Task> func)
{
this.func = func;
}
public #try(Action action)
{
this.action = action;
}
public async Task #catch<T>(Func<Task> fallback) where T : Exception
{
try
{
await func.Invoke();
}
catch(T ex)
{
await fallback.Invoke();
}
}
public void #catch<T>(Action fallback) where T : Exception
{
try
{
action.Invoke();
}
catch (T ex)
{
fallback.Invoke();
}
}
}
I've built an in-line try catch mechanic that may suit this purpose. I was going for a sort of LINQ-like or Callback function-y syntax. This is done using a couple of wrappers, a TryWrapper and a CatchWrapper so that the dot operators prompt the next steps appropriately, that implicitly cast to type of T.
You could also do something like
Try(() => UpdateSweetGreen("21", SweetGreen))
.Catch(LogToDb(e.Message))
.Catch(LogToFile(e.Message).Finally(ReportNewSweetGreen(SweetGreen);
Basically a CatchWrapper extends TryWrapper. So you could catch an exception off of another catch block. In this instance logging a failure of your method to a database, then if that fails to a file, then no matter what reporting the SweetGreen variable to some other component.
This all extends from TryWrapper
public class TryWrapper<T>
{
protected internal T Result { get; set; } = default(T);
protected internal Exception Exception { get; set; } = null;
public static implicit operator T(TryWrapper<T> wrapper)
{
return wrapper.Result;
}
public static implicit operator Exception(TryWrapper<T> wrapper)
{
return wrapper.Exception;
}
}
and CatchWrapper which simply extends TryWrapper and cannot be invoked directly, instead only appearing after a try as you'd expect with standard implementation
public class CatchWrapper<T> : TryWrapper<T>
{
}
Then a series of static extension methods
public static TryWrapper<T> Try<T>(Func<T> func)
{
var product = new TryWrapper<T>();
try
{
product.Result = func.Invoke();
}
catch (Exception e)
{
product.Exception = e;
}
return product;
}
public static TryWrapper<T> Try<T>(Action action)
{
var product = new TryWrapper<T>();
try
{
action.Invoke();
}
catch (Exception e)
{
product.Exception = e;
}
return product;
}
public static CatchWrapper<T> Catch<T>(this TryWrapper<T> wrapper, Action<Exception> response)
{
if (wrapper.Exception is null) return wrapper as CatchWrapper<T>;
response.Invoke(wrapper);
wrapper.Exception = null;
return wrapper as CatchWrapper<T>;
}
public static TryWrapper<T> Finally<T>(this TryWrapper<T> wrapper, Action<T> response)
{
response.Invoke(wrapper);
return wrapper;
}
public static TryWrapper<T> Finally<T>(this TryWrapper<T> wrapper, Func<T> response)
{
wrapper.Result = response.Invoke();
return wrapper;
}
public static TryWrapper<T> Finally<T>(this TryWrapper<T> wrapper, Action response)
{
response.Invoke();
return wrapper;
}
Now this does achieve that inline syntax the OP was asking for but I'd hazard to say its a touch less efficient since you could just deal with the exception directly in a standard try-catch. Still kindof cool to be able to specify the return directly before the Try, though this is risky if defaults to null.
I have
void foo1()
{
using(...){...}
}
void foo2()
{
using(...){...}
}
void foo3()
{
using(...){...}
}
and I have
void foo()
{
...
backgroundWorker.DoWork += (s, ev) =>
{
try
{
foo1();
foo2();
foo3();
}
catch (Exception ex)
{
// log ex
}
};
...
}
and I just read that using blocks swallow exceptions. It there an elegant way to handle exceptions from foo1(), foo2() and foo3() in foo(). I don't want to have a try/catch inside of each using block in the methods. I did stumble into this post where an extension method is suggested but I'm just checking to see if there is anything better.
FYI, Network disconnection causes the logic inside the using block to throw an exception and that's what I'm trying to handle in one common place.
Thanks,
I think I understand the confusion. Here's some pseudo-code (it may actually execute?) explaining your scenario more simply:
public class Foo
{
public void DoStuff()
{
using (var x = new Thing())
{
throw new ApplicationException("This code breaks");
}
}
private class Thing : IDisposable
{
public override Dispose()
{
throw new ApplicationException("Help, I can't dispose!");
}
}
}
This code can be thought of as the same as this code:
public class Foo
{
public void DoStuff()
{
var x = new Thing();
try
{
throw new ApplicationException("This code breaks");
x.Dispose();
}
catch (Exception err)
{
x.Dispose();
rethrow;
}
}
private class Thing : IDisposable
{
public override Dispose()
{
throw new ApplicationException("Help, I can't dispose!");
}
}
}
By using a using block, you are essentially saying, "No matter what you do, execute Dispose() on this object before moving on." However, the using block doesn't gracefully handle the case when Dispose() fails. Because of this, it never gets around to throwing the inside exception because there was another exception that pre-empted it, even if it occurred afterwards.
Does this make sense? Did I even answer your question? I'm not sure if you're looking for help understanding this or what.
My fear is that Microsoft went down the same rabbit hole here as they did with WCF.
See Avoiding Problems with the Using Statement.
Maybe they should follow their own guidelines.
In almost every (other) case a using block is a best practice.
Youcan try this code to bubble-up and exception from a using statement
Exception exc = null;
using (var x = new object())
{
try
{
// do something x, that causes an exception to be thrown
}
catch(Exception ex) { exc = ex; } // bubble-up the exception
}
if(exc != null) { throw exc; } // throw the exception if it is not null
I'm getting tossed into an existing codebase, and part of the job is to get the code gradually under test as I make updates. So it's a process of taking something old and ugly and making it nicer.
In this case, there is a code similar to this:
foreach (var thingamajigLocator in thingamajigLocators)
{
Thingamajig thingamajig;
try
{
thingamajig = thingamajigservice.GetThingamajig(thingamajigLocator);
}
catch
{
// exception logged further down, but is rethrown
continue;
}
thingamajigCollection.Add(thingamajig);
}
It's ugly and in theory, if the exception is handled further down, it shouldn't be necessary to handle it here, but that's how the code is and currently, it's too much work to handle the service code.
I would love to do something like this:
thingamajigCollection = thingamajigLocators
.Select(tl => thingamajigservice.GetThingamajig(tl))
.Where( /* some condition that strips out the ones throwing exceptions */ );
Is this possible in any way? Any other suggestions? I can certainly leave the foreach with the try/catch, but it seems like it could be more elegant since I don't care what the actual exception is in this case. Which again, I know is horrible form, and will need to be addressed, but no time for it right now.
Actually, there is no difference. Func is just a delegate. So, you can make it really straightforward:
thingamajigCollection = thingamajigLocators
.Select(tl =>
{
try
{
return thingamajigservice.GetThingamajig(tl);
}
catch(Exception)
{
return null;
}
})
.Where(t1 => t1!=null);
As an option you can wrap GetThingamajig in new method to catch exceptions there.
NOTE: As hmemcpy said swallowing exceptions isn't the best way to go. So, you better try to redesign things.
How about a method as follows:
public IEnumerable<Thingamajig> GetThingamajigs()
{
foreach (var thingamajigLocator in thingamajigLocators)
{
Thingamajig thingamajig;
try
{
thingamajig = thingamajigservice.GetThingamajig(thingamajigLocator);
}
catch
{
// exception logged higher up
// (how can this be? it just got swallowed right here)
continue;
}
yield return thingamajig;
}
}
The returned IEnumerable could then be used in a Linq statement, and the intent of the original code is not hidden in too much abstraction.
If you want to go a bit over-the-top to fairly cleanly ignore the excpetions, how 'bout something along the lines of:
thingamajigCollection =
thingamajigLocators
.Select(tl => F.Try(()=> thingamajigservice.GetThingamajig(tl)))
.Where(thing=>thing.HasValue)
.Select(thing=>thing.Value)
With the following static helper class F:
public static Maybe<T> Try<T>(Func<T> f) {
try {
return Maybe<T>.FromValue(f());
} catch (Exception e) {
return Maybe<T>.FromException(e);
}
}
public struct Maybe<T> {
readonly T val;
readonly Exception e;
Maybe(T val, Exception e) { this.val = val; this.e = e; }
public bool HasValue { get { return e == null; } }
public T Value {
get {
if (!HasValue) throw new InvalidOperationException("Attempted to get a value with an error", e);
else return val;
}
}
public static Maybe<T> FromException(Exception e) {
return new Maybe<T>(default(T), e);
}
public static Maybe<T> FromValue(T val) {
return new Maybe<T>(val, null);
}
}
I wonder exactly how is it that your exceptions are handled higher up, if you swallow and essentially ignore exceptions coming out of your service locators.
Instead of catching and swallowing the exception, I would implement a Null Object Pattern, returning a NullThingamajig from your service locators in case of an error. Then, you could simply use the following query to filter out the results:
var thingamajigs = thingamajigCollection.OfType<Thingamajig>();
EDIT
If you're unable to modify the service locators themselves, wrap them in a proxy object as well, that catches the exception and returns the null object for you:
public class ThingamajigLocatorProxy : IThingamajigLocator
{
private readonly IThingamajigLocator locator;
public ThingamajigLocatorProxy(IThingamajigLocator locator)
{
this.locator = locator;
}
public Thingamajig Locate()
{
try
{
return locator.Locate();
}
catch
{
// log exception
return new NullThingamajig();
}
}
}
Then you could use the complete query below:
var thingamajig = thingamajigLocators
.Select(locator => service.GetThingamajig(new ThingamajigLocatorProxy(locator)))
.OfType<Thingamajig>();
You could have a static helper method which does what you want:
public static KeyValuePair<T, Exception> TryExecute<T>(Func<T> func) {
try {
return new KeyValuePair<T, Exception>(func(), null);
} catch (Exception ex) {
return new KeyValuePair<T, Exception>(default(T), ex);
}
}
thingamajigCollection = thingamajigLocators
.Select(tl => TryExecute(() => thingamajigservice.GetThingamajig(tl)))
.Where(p => p.Value is null)
.Select(p => p.Key));
That should do the trick... and if you need, you can still examine the exception which has been thrown. And if you want to make it nicer, create a custom struct instead of KeyValuePair which has more suitable property names - but the concept would remain the same.
I suspect no. Any method could ultimately throw an exception.