具有派生参数的递归重载方法

Recursive overload method with derived parameter

Can anyone explain how which overloaded method is chosen when options only differ by a parameter type being derived? 例如下面的代码:

using System;

public class Program
{
    public static void LogException(AggregateException aggrException, string message)
    {
        Console.WriteLine(string.Format("{0} Inner exceptions on following logs.\n (Type: {1}); (Message: {2})", message, aggrException.GetType(), aggrException.Message, aggrException.StackTrace));
        foreach (var ie in aggrException.InnerExceptions)
            LogException(ie, "Inner Exception.");
    }

    public static void LogException(Exception exception, string message)
    {
        Console.WriteLine(string.Format("{0}\n (Type: {1}); (Message: {2})", message, exception.GetType(), exception.Message, exception.StackTrace));
        if (exception.InnerException != null)
            LogException(exception.InnerException, "Inner Exception.");
    }

    public static void Main()
    {
        var invadidOpExcep1 = new InvalidOperationException("%INVALID_OP1%");
        LogException(invadidOpExcep1, "LOG1");
        Console.WriteLine("------------------------------------------------");
        var argumentExcep1 = new ArgumentException("%ARGUMENT1%");
        LogException(argumentExcep1, "LOG2");
        Console.WriteLine("------------------------------------------------");
        var aggregateExcep1 = new AggregateException("%AGGREGATE1%", invadidOpExcep1, argumentExcep1);
        LogException(aggregateExcep1, "LOG3");
        Console.WriteLine("------------------------------------------------");
        var indORExcep1 = new IndexOutOfRangeException("%INDOR1%");
        var aggregateExcep2 = new AggregateException("%AGGREGATE2%", aggregateExcep1, indORExcep1);
        LogException(aggregateExcep2, "LOG4");
    }
}

... 产生以下输出:

LOG1
 (Type: System.InvalidOperationException); (Message: %INVALID_OP1%)
------------------------------------------------
LOG2
 (Type: System.ArgumentException); (Message: %ARGUMENT1%)
------------------------------------------------
LOG3 Inner exceptions on following logs.
 (Type: System.AggregateException); (Message: %AGGREGATE1%)
Inner Exception.
 (Type: System.InvalidOperationException); (Message: %INVALID_OP1%)
Inner Exception.
 (Type: System.ArgumentException); (Message: %ARGUMENT1%)
------------------------------------------------
LOG4 Inner exceptions on following logs.
 (Type: System.AggregateException); (Message: %AGGREGATE2%)
Inner Exception.
 (Type: System.AggregateException); (Message: %AGGREGATE1%)
Inner Exception.
 (Type: System.InvalidOperationException); (Message: %INVALID_OP1%)
Inner Exception.
 (Type: System.IndexOutOfRangeException); (Message: %INDOR1%)

日志 1 到 3 没问题。在前两个中,InvalidOperationExceptionArgumentException 都是 Exception 而不是 AggregateException,所以带 ExceptionLogException 是叫。在第三个中,传递了一个 AggregateException,因此调用了将该类型作为参数的重载。 但是在日志 4 上,传递一个 AggregateException 有另一个 AggregateException 'inside',我预计它会调用 AggregateException 重载两次,意思是,我预计第 4 个日志是:

LOG4 Inner exceptions on following logs.
 (Type: System.AggregateException); (Message: %AGGREGATE2%)
Inner Exception. Inner exceptions on following logs.
 (Type: System.AggregateException); (Message: %AGGREGATE1%)
Inner Exception.
 (Type: System.InvalidOperationException); (Message: %INVALID_OP1%)
Inner Exception.
 (Type: System.ArgumentException); (Message: %ARGUMENT1%)
Inner Exception.
 (Type: System.IndexOutOfRangeException); (Message: %INDOR1%)

任何人都可以阐明这里发生的事情吗?

提前致谢。

AggregateException.InnerExceptions 是类型 System.Collections.ObjectModel.ReadOnlyCollection<Exception>。这意味着您的 foreach 变量 ieException 类型。因为 LogException 的调用是静态调度的(在编译时),所以编译器选择具有 Exception 签名的重载。

方法调用在编译时解决。在 Log 4 上,您传递了一个 AggregateException,并且正如您所期望的那样,调用了 LogException(AggregateException, string)

然后,在 InnerException 的结果上调用 LogExceptionInnerExceptionreturns一个Exception,所以调用LogException(Exception, string)。实际返回的运行时类型无关紧要,因为解析是在编译时完成的。