Question

What argument should SafeRun has to correctly handle following call scenarios?

SafeRun(new SomeClass(arg1, arg2));
SafeRun(new SomeOtherClass());
SafeRun(someObject.FooReturningVoid());

I've tried the following but without success :(

protected void SafeAct<TResult>(Expression<Func<TResult>> expression)
protected void SafeAct(Expression<Action> expression)

SafeRun actually does this:

protected void SafeAct<TResult>(Expression<Func<TResult>> expression)
{
    try
    {
        Expression.Lambda<Func<TResult>>(expression).Compile()();
    }
    catch (Exception e)
    {
        ThrownException = e;
    }
}

I do not accept an alternative of calling SafeAct with an lambda expression!:

I DON'T WANT THIS:
SafeRun(() => new SomeClass());
Was it helpful?

Solution

You can't do this, because these two calls just return object instance, which cannot be casted to expression

SafeRun(new SomeClass(arg1, arg2));
SafeRun(new SomeOtherClass());

And passing void is not allowed in C# at all

SafeRun(someObject.FooReturningVoid());

Take a look on applicable function member verification, you'll see that

A function member is said to be an applicable function member with respect to an argument list A when all of the following are true:

The number of arguments in A is identical to the number of parameters in the function member declaration.

For each argument in A, the parameter passing mode of the argument (that is, value, ref, or out) is identical to the parameter passing mode of the corresponding parameter, and for a value parameter or a parameter array, an implicit conversion (Section 6.1) exists from the type of the argument to the type of the corresponding parameter

In your case there is no implicit conversion exists from the type of argument (SomeClass, SomeOtherClass) to parameter's Expression<Action> type. Your code will work only if you will define implicit conversions between expression type and types you are passing to method.

OTHER TIPS

For the first call make an interface ISafeRunable that exposes a method void Run() (kinda like Threads in Java). The prototype should look like this void SafeRun(IRunable).

For the second call make a delegate or just use the Action delegate. The prototype should look like this void SafeRun(Action actionDelegate). And call it like this SafeRun(someObject.VoidFunction);

Have you tried using delegates?

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace throw_test
{
    class Program
    {
        static void Main(string[] args)
        {
            Program p = new Program();

            p.Run();
        }

        public delegate void SafeRunDelegate(object sender, EventArgs e);

        public void Run()
        {
            this.SafeRun(this.MyMethodToSafelyRun);
        }

        public void SafeRun(SafeRunDelegate d)
        {
            if (d != null)
                d(this, new EventArgs());
        }

        public void MyMethodToSafelyRun(object sender, EventArgs e)
        {
        }
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top