c# – 具有相同名称的静态方法和扩展方法

前端之家收集整理的这篇文章主要介绍了c# – 具有相同名称的静态方法和扩展方法前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我创建了扩展方法
public static class XDecimal
{
    public static decimal Floor(
        this decimal value,int precision)
    {
        decimal step = (decimal)Math.Pow(10,precision);
        return decimal.Floor(step * value) / step;
    }
}

现在我尝试使用它:

(10.1234m).Floor(2)

但编译器说使用实例引用无法访问成员’decimal.Floor(decimal)’;用类型名称来限定它.我明白有静态decimal.Floor(十进制)方法.但它有不同的签名.为什么编译器无法选择正确的方法

解决方法

你在这里有两个好的和正确的答案,但我理解简单引用规范的答案并不总是那么有启发性.让我补充一些其他细节.

你可能有一个重载分辨率的心智模型,如下所示:

>将所有可能的方法放在一个大桶中 – 扩展方法,静态方法,实例方法等.
>如果存在可能使用的错误方法,请将其从存储桶中删除.
>在其余方法中,选择与参数类型具有最佳匹配参数表达式的唯一方法.

虽然这是很多人的超载分辨率的心理模型,但遗憾的是它是巧妙的错误.

真正的模型 – 我将在这里忽略泛型类型推断问题 – 如下:

>将所有实例和静态方法放入存储桶中.虚拟覆盖不计为实例方法.
>消除不适用的方法,因为参数与参数不匹配.

在这一点上,我们要么有方法,要么我们没有.如果我们在桶中有任何方法,则不检查扩展方法.这是重要的一点.该模型不是“如果正常的重载分辨率产生错误,那么我们检查扩展方法”.该模型是“如果正常的重载分辨率没有产生任何适用的方法,那么我们检查扩展方法”.

如果存储桶中有方法,则会更多地消除基类方法,最后根据参数与参数的匹配程度选择最佳方法.

如果碰巧选择静态方法,那么C#将假设您打算使用类型名称错误地使用实例,而不是您希望搜索扩展方法.重载分辨率已经确定存在一个实例或静态方法,其参数与您给出的参数匹配,并且它将选择其中一个或给出错误;它不会说“哦,你可能打算把这个古怪的扩展方法称为恰好在范围内”.

我知道从你的角度来看这很令人烦恼.您显然希望模型“如果重载决策产生错误,则回退到扩展方法”.在您的示例中,这将是有用的,但此行为会在其他方案中产生不良结果.例如,假设你有类似的东西

mystring.Join(foo,bar);

这里给出的错误是它应该是string.Join.如果C#编译器说“哦,string.Join是静态的,那将是奇怪的.用户可能意味着使用连接字符序列的扩展方法,让我试试……”然后你收到一条错误信息说序列连接运算符 – 这里没有任何关于你的代码的东西 – 没有正确的参数.

或者更糟糕的是,如果通过一些奇迹你确实给它的参数有效但是打算调用静态方法,那么你的代码将以一种非常奇怪且难以调试的方式被破坏.

扩展方法在游戏的最后阶段添加,并且查找它们的规则使得他们故意更喜欢给出神奇的工作错误.这是一个安全系统,以确保扩展方法不受意外的约束.

猜你在找的C#相关文章