Mike de Klerk
Mike de Klerk

Reputation: 12328

Inline functions as code snippet / template

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

Answers (1)

Random Dev
Random Dev

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.

make it Monadic

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);
}

example usage of 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

Related Questions