Mike
Mike

Reputation: 850

Calling extension method's overload with derived type

Simplified, i have these 2 Extension method:

public static class Extensions
{
    public static string GetString(this Exception e)
    {
        return "Standard!!!";
    }
    public static string GetString(this TimeoutException e)
    {
        return "TimeOut!!!";
    }
}

And here is where i use them:

try
{
    throw new TimeoutException();
}
catch (Exception e)
{
    Type t = e.GetType(); //At debugging this a TimeoutException
    Console.WriteLine(e.GetString()); //Prints: Standard
}

I have more GetString() extensions.

My try{...}catch{...} is getting large and basically i search for ways to shorten it down to 1 catch that calls the extension based on the type of the exception.

Is there a way to call the right extension method at runtime?

Upvotes: 11

Views: 407

Answers (2)

Spotted
Spotted

Reputation: 4091

Extension methods are the wrong tool here.

I would foster the use of polymorphism to solve your problem:

public abstract class BaseException : Exception
{
    public abstract string GetString();
}

public sealed class TimeoutException : BaseException
{
    public override string GetString() => "TimeOut!!!";
}

public sealed class MyException : BaseException
{
    public override string GetString() => "Standard!!!";
}

Usage

try
{
    throw new TimeoutException(); //or whatever BaseException's children
}
catch (BaseException e)
{
    //here I'm assuming you know that you are swallowing the exception (which may be an anti-pattern)
    Console.WriteLine(e.GetString());
}

Edit

It looks like you have not the full control over which and when exceptions are thrown. Another possibility would be to add 1 catch clause for each behavior (rather than for each exception type) and get rid of GetString():

try
{
    throw new TimeoutException();
}
catch (Exception e) when (e is ArgumentNullException || e is FormatException)
{
    //do something
}
catch (Exception e) when (e is TimeoutException)
{
    //do something
}
catch (Exception e)
{
    throw new NotImplementedException($"Hey Mike, write something for {e.GetType()}, will ya?"); //idea from Jeroen
}

Upvotes: -1

Alessandro D'Andria
Alessandro D'Andria

Reputation: 8868

As Yacoub Massad suggests you can use dynamic, because with dynamic method overload resolution is deferred at runtime through late binding.:

public static class Extensions
{
    public static string GetString<T>(this T e) where T : Exception
    {
        // dynamic method overload resolution is deferred at runtime through late binding.
        return GetStringCore((dynamic)e);
    }

    static string GetStringCore(Exception e)
    {
        return "Standard!!!";
    }

    static string GetStringCore(TimeoutException e)
    {
        return "TimeOut!!!";
    }

    static string GetStringCore(InvalidOperationException e)
    {
        return "Invalid!!!";
    }
}

This should make the trick.

Upvotes: 4

Related Questions