通用扩展方法解析失败
以下程序无法编译,因为在出错的行中,编译器选择使用单个T
参数作为分辨率的方法,因为List
不适合单个T
的通用约束而失败。 编译器无法识别可以使用的其他方法。 如果我删除了单T
方法,编译器将正确地找到许多对象的方法。
我已经阅读了两篇关于通用方法解析的博客文章,其中一篇来自JonSkeet,另一篇来自Eric Lippert,但我无法找到解释或解决问题的方法。
显然,使用两个具有不同名称的方法会起作用,但我喜欢这样一个事实:对于这些情况,您只有一种方法。
namespace Test { using System.Collections.Generic; public interface SomeInterface { } public class SomeImplementation : SomeInterface { } public static class ExtensionMethods { // comment out this line, to make the compiler chose the right method on the line that throws an error below public static void Method(this T parameter) where T : SomeInterface { } public static void Method(this IEnumerable parameter) where T : SomeInterface { } } class Program { static void Main() { var instance = new SomeImplementation(); var instances = new List(); // works instance.Method(); // Error 1 The type 'System.Collections.Generic.List' // cannot be used as type parameter 'T' in the generic type or method // 'Test.ExtensionMethods.Method(T)'. There is no implicit reference conversion // from 'System.Collections.Generic.List' to 'Test.SomeInterface'. instances.Method(); // works (instances as IEnumerable).Method(); } } }
方法分辨率表示越接近越好 。 有关确切规则,请参阅博客文章。
什么是更接近的意思? 编译器将查看它是否可以找到完全匹配,如果由于某种原因找不到它将找到下一个可能的兼容方法等等。
让我们首先通过删除SomeInterface
约束来编译该方法。
public static class ExtensionMethods { public static void Method(this T parameter) //where T : SomeInterface { } public static void Method (this IEnumerable parameter) //where T : SomeInterface { } }
现在编译器很乐意编译,并注意两个方法调用Goes to Method(T)
而不是Method(IEnumerable
。 这是为什么?
因为Method(T)
在某种意义上更接近,可以将任何类型作为参数,也不需要任何转换。
为什么
Method(IEnumerable
不接近?)
这是因为您将变量的编译时类型设置为List
,因此需要从List
到IEnumerable
的引用转换。 哪个更接近,但根本没有做任何转换。
回到你的问题。
为什么是
instances.Method();
不编译?
再次,如前所述使用Method(IEnumerable
我们需要一些引用转换,所以显然不是更接近。 现在我们只剩下一种方法,它与Method
非常接近。 但问题是你用SomeInterface
限制了它,并且明确List
不能转换为SomeInterface
。
问题是(猜测)在编译器选择更近的重载之后检查通用约束。 在这种情况下,这会使选择的最佳过载无效。
您可以通过将变量的静态类型更改为可以工作的IEnumerable
来轻松修复它,现在您知道原因了。
IEnumerable instances = new List ();
您是否尝试过在没有generics的情况下实现第一个,因为它应该表现相同:
public static void Method(this SomeInterface parameter) { /*...*/ }
或者,正如德米特里建议的那样,通过以下方式呼叫第二个:
instances.Method();
但是在这里你需要为每次调用添加
…
-
虽然我知道你不想要它,但我认为你应该重新思考方法名称应该是否相同。 我看不出同一名称如何对一个实例起作用,以及这些实例的集合。 例如,如果您的方法名称是
Shoot
forT
,那么另一种方法应该听起来像ShootThemAll
或类似的东西。 -
否则你应该让你的作业略有不同:
IEnumerable
instances = new List (); instances.Method(); //now this should work -
作为最后一个选项,正如Dimitry在评论中所说,你必须明确指定类型参数。
上述就是C#学习教程:通用扩展方法解析失败分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
instances.Method
();
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1029909.html