首页 > 解决方案 > 当唯一的区别是可选参数时,为什么 C# 允许重载?

问题描述

为什么 C#/Framework 允许我使用可选参数来创建它不允许的重载?

public static TOut? NullableConvert<TOut>(object source, Func<object, TOut> converter) where TOut : struct
{
}

public static TOut NullableConvert<TOut>(object source, Func<object, TOut> converter) where TOut : class
{
}

当我尝试上述重载时,我得到以下我同意的错误:

错误 CS0111 类型“DataHelpers”已经定义了一个名为“NullableConvert”的成员,具有相同的参数类型


但是,如果我将可选参数添加到如下所示的方法之一,那么我可以使用这些重载(请注意object x = null)。

public static TOut? NullableConvert<TOut>(object source, Func<object, TOut> converter) where TOut : struct
{
}

public static TOut NullableConvert<TOut>(object source, Func<object, TOut> converter, object x = null) where TOut : class
{
}

当我按照运行时运行时解决了没有可选参数的正确重载

long? x = DataHelpers.NullableConvert(DBNull.Value, Convert.ToInt64);
string y = DataHelpers.NullableConvert(DBNull.Value, Convert.ToString);

编译器/运行时如何在没有可选参数的情况下解决重载?

如果可以解决方法,为什么我首先会收到错误?

标签: c#.net-coreoverloading

解决方案


不允许方法重载仅在返回类型上有所不同(以及通用定义,只是为了完整性)。

另一方面,对具有可选参数的方法的所有调用都只是编译为调用站点上具有默认值的调用。所以在你的情况下,编译器将把这个

NullableConvert(DB.Value, Convert.ToString)

进入这个:

NullableConvert(DB.Value, Convert.ToInt64, null)

在改变方法的同时

public static TOut NullableConvert<TOut>(object source, Func<object, TOut> converter, object x = null) where TOut : class
{
}

进入这个:

public static TOut NullableConvert<TOut>(object source, Func<object, TOut> converter, object x) where TOut : class
{
}

但是,没有理由也替换该方法struct,因为没有为该方法定义可选参数。所以在IL中存在以下两种方法:

public static TOut NullableConvert<TOut>(object source, Func<object, TOut> converter, object x) where TOut : class
{
}
public static TOut? NullableConvert<TOut>(object source, Func<object, TOut> converter) where TOut : struct
{
}

因此,对 will 的调用NullableConvert(DB.Value, Convert.ToString)不会编译为上述重载,因为TOut: struct.

所以简而言之,在编译器尝试解决任何重载之前,它会替换任何具有可选参数的方法。


推荐阅读