c# - 为什么编译器选择字符串而不是隐式字符数组的扩展方法?
问题描述
如果我已经System.Linq
导入,我可以在以下调用中使用这个 ToArray 重载:
var x = "foo".ToArray();
并被x
分配了char[]
三个元素,它们是字符串中的字符"foo"
。然后,如果我在范围内添加自定义扩展方法:
public static T[] ToArray<T>(this T toConvert) => new[] { toConvert };
编译器默默地改变了主意,x
变成了一个string[]
只有一个元素的字符串"foo"
。
为什么编译器不抱怨歧义?我知道编译器会自动解决一些看似模棱两可的情况而不会出错,但我找不到任何关于这种情况的文档或参考资料。基本上,似乎将 astring
视为 astring
而不是隐式数组char
似乎是首选行为......
解决方案
您引用的第一个扩展方法:
public static TSource[] ToArray<TSource> (this System.Collections.Generic.IEnumerable<TSource> source);
将 an 转换IEnumerable<TSource>
为数组(泛型类型的接口)。
您制作的第二种扩展方法:
public static T[] ToArray<T>(this T toConvert) => new[] { toConvert };
将任何 T 对象转换为单个对象数组。由于这是一种没有接口的泛型类型,因此它优于采用具有泛型类型的接口的扩展方法。本质上,与泛型类型的接口相比,应用扩展的潜在类型覆盖面更大。编译器将更喜欢与扩展方法匹配的具体类型,而不是匹配的接口。
C# 语言规范,向下查找约 60% Method Overloading
:
https ://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/introduction
VB 版本,虽然主要适用于 C#: https ://docs.microsoft.com/en-us/dotnet/visual-basic/reference/language-specification/overload-resolution
推荐阅读
- c++ - gem5 模拟:goodbye.sayGoodbye(myName) 调用时出错
- mysql - 聚合来自 UNION 集合运算符的值
- reactjs - 考虑到我想向数据库发出发布请求,初始状态属性应该在 react-redux 减速器中为空还是未定义?
- autodesk-forge - 锻造设计自动化中的 Aec 组件
- ios - ARKit 和 SceneKit。如何根据 IOS swift 中检测到的图像锚物理宽度触发 action/play_video
- angular7 - 在Angular 7中的两个不同组件之间传递数据
- javascript - 获取用户组长并设置输入字段的值
- c# - 如何从 asp net core 中的 AuthorizationFilter 重定向到登录页面?
- ethereum - 版本化的 Solidity 智能合约
- azure-data-factory-2 - ADF 创建 REST 数据集 BUG