首页 > 解决方案 > 为什么编译器选择字符串而不是隐式字符数组的扩展方法?

问题描述

如果我已经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似乎是首选行为......

标签: c#.netstringcharambiguity

解决方案


您引用的第一个扩展方法:

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 Overloadinghttps ://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/introduction

C# 重载解决方案: https ://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-7.3/improved-overload-candidates

VB 版本,虽然主要适用于 C#: https ://docs.microsoft.com/en-us/dotnet/visual-basic/reference/language-specification/overload-resolution


推荐阅读