I like using implicit typing for almost everything because it's clean and simple. However, when I need to wrap a try...catch block around a single statement, I have to break the implicit typing in order to ensure the variable has a defined value. Here's a contrived hypothetical example:
var s = "abc";
// I want to avoid explicit typing here
IQueryable<ABC> result = null;
try {
result = GetData();
} catch (Exception ex) { }
if (result != null)
return result.Single().MyProperty;
else
return 0;
Is there a way I can call GetData()
with exception handling, but without having to explicitly define the type of the result variable? Something like GetData().NullOnException()
?
This is a common problem. I recommend that you just stick with your existing solution.
If you really want an alternative, here it is:
static T NullOnException<T>(Func<T> producer) where T : class {
try { return producer(); } catch { return null; } //please modify the catch!
}
//now call it
var result = NullOnException(() => GetData());
Please modify this to log the exception or restrict the catch to a concrete type. I do not endorse swallowing all exceptions.
As this answer is being read a lot I want to point out that this implementation is just of demo-quality. In production code you probably should incorporate the suggestions given in the comments. Write yourself a robust, well-designed helper function that will serve you well for years.
Just put your code inside the try:
var s = "abc";
// I want to avoid explicit typing here
try {
var result = GetData();
if (result != null)
return result.Single().MyProperty;
else
return 0;
} catch (Exception ex) { }
I came to a similar solution as @usr, but with slightly different semantics:
T LiftScope<T>(Func<T> ScopedFunction)
{
T result = ScopedFunction();
return result;
}
The purpose of LiftScope
is to carry an internal variable out to the caller without compromising implicit typing. This could be used to solve the original problem, except that the try...catch
would actually be embedded in the call.
try...catch
var result =
LiftScope(() => {
try { return producer(); } catch { return null; }
});
Now the caller is able to be responsible for exception handling. Furthermore, this can be used generically in a handful of similar use-cases where you have very short-lived scopes.
if
var result =
LiftScope(() => {
if (a == b)
return GetData(true);
else if (b == c)
return GetData(false);
else
return GetData(true, 2);
});
This could also be solved with a ternary-style if
statement.
using
var result =
LiftScope(() => {
using (var myContext = new MyDataContext())
{
return myContext.MyTable.Where(w => w.A == B).ToList();
}
});