使用派生类型调用扩展方法重载
Calling extension method's overload with derived type
简化了,我有这2个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 个捕获,根据异常类型调用扩展。
有没有办法在运行时调用正确的扩展方法?
正如 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!!!";
}
}
这应该可以解决问题。
这里的扩展方法是错误的工具。
我会促进使用多态性来解决你的问题:
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
}
简化了,我有这2个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 个捕获,根据异常类型调用扩展。
有没有办法在运行时调用正确的扩展方法?
正如 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!!!";
}
}
这应该可以解决问题。
这里的扩展方法是错误的工具。
我会促进使用多态性来解决你的问题:
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
}