为了账号安全,请及时绑定邮箱和手机立即绑定

使用派生类型调用扩展方法的重载

使用派生类型调用扩展方法的重载

C#
冉冉说 2021-07-14 17:05:53
简化,我有这两种Extension方法:public static class Extensions{    public static string GetString(this Exception e)    {        return "Standard!!!";    }    public static string GetString(this TimeoutException e)    {        return "TimeOut!!!";    }}这是我使用它们的地方:try{    throw new TimeoutException();}catch (Exception e){    Type t = e.GetType(); //At debugging this a TimeoutException    Console.WriteLine(e.GetString()); //Prints: Standard}我有更多的GetString()扩展。我try{...}catch{...}的越来越大,基本上我正在寻找方法将其缩短为 1 个根据异常类型调用扩展的捕获。有没有办法在运行时调用正确的扩展方法?
查看完整描述

2 回答

?
海绵宝宝撒

TA贡献1809条经验 获得超8个赞

正如 Yacoub Massad 建议您可以使用dynamic,因为dynamic方法重载解析在运行时通过后期绑定推迟:


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!!!";

    }

}

这应该可以解决问题。


查看完整回答
反对 回复 2021-07-17
?
慕姐4208626

TA贡献1852条经验 获得超7个赞

扩展方法在这里是错误的工具。


我会提倡使用多态来解决您的问题:


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!!!";

}

用法


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

}

编辑

看起来您无法完全控制引发异常的时间和地点。另一种可能性是为每个行为(而不是每个异常类型)添加 1 个 catch 子句并删除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

}


查看完整回答
反对 回复 2021-07-17
  • 2 回答
  • 0 关注
  • 208 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信