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是静态的,那将是奇怪的.用户可能意味着使用连接字符序列的扩展方法,让我试试……”然后你收到一条错误信息说序列连接运算符 – 这里没有任何关于你的代码的东西 – 没有正确的参数. 或者更糟糕的是,如果通过一些奇迹你确实给它的参数有效但是打算调用静态方法,那么你的代码将以一种非常奇怪且难以调试的方式被破坏. 扩展方法在游戏的最后阶段添加,并且查找它们的规则使得他们故意更喜欢给出神奇的工作错误.这是一个安全系统,以确保扩展方法不受意外的约束. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |