Reputation: 12328
EDIT: Basically I want to be able to use the following mechanism as an answer to my original question:
void MethodA()
{
MethodB();
//This code will never be reached because 'return' from the inline MethodB is executed.
//... More code here
}
[Attribute(Inline)]
ReturnValue MethodB()
{
return;
}
Of course the example above is useless on its own, more logic will be put in MethodB of course but I left it out for brevity.
Original question:
In a project that is already 1 year under development there is chosen to do the following. Instead of throwing exceptions, each functions returns a ReturnValue<T>
on which a IsSuccessFul
boolean flag lives. It is used like this
var methodResult = MyMethod();
if (!methodResult .IsSuccesful)
{
return new ReturnValue<Type>(methodResult .ThrownException);
}
var value= methodResult.Value;
This way of calling methods is used on every public function in the project. You can image that this requires more lines of code than var value = MyMethod();
with a generic try catch. Especially if a dozen of public functions are called in a scope.
Please don't argue with the chosen design, I am not here to debate whether this is a good choice or not.
What I want to know is this: Is there a way I can do this
var value= TryMethod(MyMethod);
And that the compiler, or some plugin, or whatever, transforms this precompile time to the full pattern shown earlier. My point is, if !IsSuccessFul the function should return. I could write a precompile time command that does this for me but I was hoping at some kind of snippet/template/inline way of VisualStudio itself.
Thanks.
Upvotes: 1
Views: 161
Reputation: 52280
should be as easy as (for the pattern - which of course here is rather useless because it's basically the identity, only that it will recreate another ReturnValue<T>
- so not advised):
public static ReturnValue<T> TryMethod<T>(Func<ReturnValue<T>> method)
{
var methodResult = method();
if (!methodResult .IsSuccesful)
return new ReturnValue<T>(methodResult.ThrownException);
// I can only guess at this:
return methodResult;
}
but based on your usage I think you really want:
public static T TryMethod<T>(Func<ReturnValue<T>> method)
{
var methodResult = method();
if (!methodResult .IsSuccesful)
throw methodResult.ThrownException;
return methodResult.Value;
}
of course you might have to make multiple overloads (when your method takes parameters - like:
public static T TryMethod<T,P>(Func<P,ReturnValue<T>> method, P p)
{
var methodResult = method(p);
// ...
and you might want to put those into a static extension class and do:
public static T TryMethod<T>(this Func<ReturnValue<T>> method)
so you can write
var value = MyMethod.TryMethod();
and so on.
Overall your design might not be to bad but you should consider adding the usual functor-map and mondadic-bind operations (you could even use LINQ when you do SelectMany
) to your ReturnValue<T>
type:
public static ReturnValue<B> Map<A,B>(this ReturnValue<a> v, Func<A,B> f)
{
if (v.IsSuccesful) return new ReturnValue<B>(f(v.Value));
return new ReturnValue<B>(v.ThrownException);
}
public static ReturnValue<B> Bind<A,B>(this ReturnValue<a> v, Func<A,ReturnValue<B>> f)
{
if (v.IsSuccesful) return f(v.Value);
return new ReturnValue<B>(v.ThrownException);
}
Bind
using this Bind
here you can do this instead and I think that is what you meant with scope:
method().Bind(
value => {
// ... whatever you want to do with value - just return a ReturnValue<> at the end
});
Upvotes: 3