Dan*_*zen 10 .net c# generics generic-type-argument generic-method
请检查以下代码段:
public interface ICountable { }
public class Counter<T>
where T : ICountable
{
public int Count(IEnumerable<T> items)
{
return 0;
}
public int Count(T Item)
{
return 0;
}
}
public class Counter
{
public int Count<T>(IEnumerable<T> items)
where T : ICountable
{
return 0;
}
public int Count<T>(T Item)
where T : ICountable
{
return 0;
}
}
Run Code Online (Sandbox Code Playgroud)
Counter的两个版本仅在泛型参数的规范上有所不同.其中一个定义为泛型类型参数,另一个定义为泛型参数.两者都限制方法参数以实现ICountable接口.我将分别称他们为具体和非具体.
现在,我定义了一个实现ICountable接口的类,以及一组实例:
public class CItem : ICountable { }
var countables = new List<CItem>();
Run Code Online (Sandbox Code Playgroud)
然后,我想在集合中使用两个Counter类.
var specific = new Counter<CItem>();
var nonspecific = new Counter();
specific.Count(countables);
nonspecific.Count(countables);
Run Code Online (Sandbox Code Playgroud)
特定计数器识别countables集合应该属于签名int Count(IEnumerable),但非特定版本不会.我收到错误:
类型'
System.Collections.Generic.List<CItem>'不能T在泛型类型或方法'Counter.Count<T>(T)'中用作类型参数' '.没有从List<CItem>'到的隐式引用转换ICountable.
似乎非特定版本对集合使用了错误的签名.
他们为什么表现不同?如何指定非特定版本以使其行为与另一个相同?
注意:我知道这个例子是不现实的.但是,我在一个非常复杂的场景中使用扩展方法遇到了这个问题.为简单起见,我使用这些类
提前致谢
非特定类的问题是编译器在编译时不知道类型 T,这就是它无法为 method 选择正确的重载的原因Count<T>()。但是,如果您设置泛型类型约束,编译器现在知道需要什么类型......
如果您用签名注释掉您的方法,public int Count<T>(T Item)它将编译,因为它将使用具有正确签名的方法(即public int Count<T>(IEnumerable<T> items))
如果您通过将 List 显式转换为帮助编译器推断类型,它也将编译并运行IEnumerable<CItem>:
nonspecific.Count(countables as IEnumerable<CItem>);
Run Code Online (Sandbox Code Playgroud)
看看简化的场景:
static string A<T>(IEnumerable<T> collection)
{
return "method for ienumerable";
}
static string A<T>(T item)
{
return "method for single element";
}
static void Main(string[] args)
{
List<int> numbers = new List<int>() { 5, 3, 7 };
Console.WriteLine(A(numbers));
}
Run Code Online (Sandbox Code Playgroud)
输出:“单个元素的方法”