C#运行时选择的重载方法

时间:2017-08-30 19:47:23

标签: c# inheritance exception-handling overloading

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作为参数并被称为具有异常的那个?

3 个答案:

答案 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);

您将获得正确的方法调用。