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



有人能解释一下,当选项只因派生的参数类型而异时,如何选择重载方法吗?例如,以下代码:

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都是Exceptions,而不是AggregateExceptions,因此调用取ExceptionLogException。在第三个例子中,传递了一个AggregateException,因此调用了将该类型作为参数的重载。但在日志4上,通过一个"内部"有另一个AggregateExceptionAggregateException,我预计它会调用两次AggregateException过载,这意味着,我预计第四个日志是:

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变量ie的类型为Exception。因为LogException的调用是静态调度的(在编译时(,所以编译器选择具有Exception签名的重载。

方法调用在编译时解析。在Log4中,您传递一个AggregateException,正如您所期望的,LogException(AggregateException, string)被调用。

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

最新更新