Joseph Carras
Joseph Carras

Reputation: 610

How to convert a generic C# Action<T1> to Action<T2>

I have been doing some work with C# to learn and create something; unfortunately I am very new to C# I am having some trouble with casts.

I have an Action of a Type1 and I want to convert it to Type2; Both types are known during compile time. Here is the sample code of what I am trying to archive.

public class Example <Resolve, Reject>
{
    protected Resolve resolved;
    protected Reject rejected;

    public Example( Resolve value ) { resolved = value; }
    public Example( Reject value ) { rejected = value;  }

    public void invoke( Action<Resolve> callback ) {
        if( null != resolved ) { callback (resolved ); }
        else if( null != rejected ) {
            // How to cast action from Action <Resolve> to Action <Rejected>
            // and invoke it with the rejected value??
            callback ( rejected );
        }
        else throw new ApplicationException( "Not constructed" );
    }
}

public static void Main (string[] args)
{
    Console.WriteLine ("Start");

    var example1 = new Example <string, System.ArgumentException> ( "Str argument" );

    example1.invoke (msg => {
        // Here the msg is a string ok!
        if (msg is string) { Console.WriteLine (msg); }
        else { Console.WriteLine ("Exception"); }
    });

    var example2 = new Example <string, System.ArgumentException> ( new ArgumentException("An exception") );

    example2.invoke (msg => {
        // Here msg should be an ArgumentException.
        if (msg is string) { Console.WriteLine (msg); }
        else { Console.WriteLine ("Exception"); }
    });


    Console.WriteLine ("Done");
    Console.ReadLine ();
}

I have no control over the types so I can't cast one to another, and even if I could the spec I am implementing has the requirement that I have to resolve the callback with either the Resolve or Reject value depending on some conditions that happen during run-time.

Can you help me out please?

Upvotes: 1

Views: 100

Answers (1)

David Arno
David Arno

Reputation: 43254

Disclaimer: I am the author of the following open source library

If you use a discriminated union type and pattern matching, as offered by Succinc<T>, you could simply write what you require here as:

public static void MessageOrException(Union<string, ArgumentException> value)
{
    value.Match().Case1().Do(Console.WriteLine)
                 .Else(Console.WriteLine("Exception")
                 .Exec();
}


public static void Main (string[] args)
{
    Console.WriteLine ("Start");

    var example1 = new Union<string, ArgumentException> ("Str argument");
    MessageOrException(example1);  // Writes "Str argument"

    var example2 = 
        new Union<string, ArgumentException>(new ArgumentException("An exception"));
    MessageOrException(example2); // Writes "Exception"

    Console.WriteLine ("Done");
    Console.ReadLine ();
}

Upvotes: 1

Related Questions