namespace Rextester
{
public class BaseException : Exception
{
public BaseException() { }
}
public class Program
{
public static void MethodA(BaseException e)
{
Console.WriteLine("BaseException");
}
public static void MethodA(Exception e)
{
Console.WriteLine("Exception");
}
public static void Main(string[] args)
{
try
{
throw new BaseException();
}
catch (Exception e)
{
Console.WriteLine(e.GetType());
MethodA(e);
}
}
}
}
大家好我根据上面执行的代码的结果有一个问题:
e.GetType()== Rextester.BaseException
MethodA写入控制台:异常
因此,即使异常的类型是派生类,为什么在运行时没有调用特定的重载方法,该方法具有BaseException作为参数并被称为具有异常的那个?
答案 0 :(得分:4)
在以下try / catch块中:
try
{
throw new BaseException();
}
catch (Exception e)
{
Console.WriteLine(e.GetType());
MethodA(e);
}
抛出异常并且在catch处,异常的类型是Exception
,而不是BaseException
。你基本上扔了BaseException
,但BaseException
继承了Exception
。所以你进入了阻止区块。
如果你想抓住BaseException
,你应该首先抓住这个,因为它更具体。
try
{
throw new BaseException();
}
catch (BaseException e)
{
Console.WriteLine(e.GetType());
MethodA(e);
}
catch (Exception e)
{
Console.WriteLine(e.GetType());
MethodA(e);
}
顺便说一下,名称DerivedException
比名称BaseException
更清晰。 .NET中的所有异常类型以及自定义异常类型,我们为需求定义的异常类型都继承自Exception
类。所以它们都是类Exception
的派生类。
上面也可以找到here,如下所示:
例外具有以下属性:
- 例外是所有最终派生自System.Exception的类型。
- 一旦try块发生异常,控制流就会将跳转到存在的第一个关联异常处理程序 调用堆栈中的任何位置。在C#中,catch关键字用于定义 异常处理程序。
除了上述内容之外,您会发现this的内容很有帮助,其中声明
可以将具有不同异常过滤器的多个catch块链接在一起。 在代码中从上到下评估catch块,但是 对于抛出的每个异常,只执行一个catch块。 第一个catch块,指定确切的类型或基类 抛出的异常被执行。如果没有catch块指定a 匹配异常过滤器,一个没有过滤器的catch块 如果声明中存在一个,则被选中。 非常重要 位置捕获具有最具体(即最)的块 首先派生的)异常类型。
答案 1 :(得分:0)
函数MethodA
被声明为static。因此,任何对函数的绑定都是在编译时。
答案 2 :(得分:0)
重载的方法在编译时绑定。
在编译时,e
的类型为Exception
。
这就是原因。
该方法是否为静态都无关紧要。两者都是编译时间。
但是当您捕获到异常之后,您可以做
dynamic dynEx = e;
MethodA(dynEx);
您将获得正确的方法调用。