[英]Question about generic function parameter
我只是想知道为什么将System.Collections.Generic.List<string>
传递给此函数test(ICollection<object> t)
将不起作用,为什么我不能像将string
传递给test2(object t)
?
对我来说没有多大意义!
因为ICollection
不是仅输出接口,所以它不是协变的。
考虑以下代码:
void test(ICollection<object> t)
{
t.Add(new TextBox());
}
List<string> lst;
test(lst);
当test
试图将TextBox
塞入List<string>
时应该发生什么?
ICollection<object>
的约定是可以放入任何object
,并且输出的项目始终为object
类型。 但是List<string>
仅满足该合同的一半。
因为在C#3.0和.NET 3.5或更低版本中, List<T>
实现ICollection<T>
。 这意味着List和ICollection的通用类型必须相同。 在这种情况下,尽管字符串是从对象派生的,但不能将List<sting>
分配给List<object>
。 不能以相同的方式将List<string>
分配给ICollection<object>
。
在C#4.0和.NET 4.0中,我们具有协方差和逆方差的概念,可让您将List<string>
分配给IEnumerable<object>
。
这是一段可在C#4.0中运行的代码
public static void Test(IEnumerable<object> input) {
// do something
}
static void Main(string[] args) {
var input = new List<string>();
Test(input);
}
方法test()
期望参数值具有实现接口ICollection<object>
。 确保类List
可以。
@Ben的解释很棒,是的,@ Gallahad建议,.Net 4.0中实现了有用的协变和逆变接口。 这些使您能够执行与您尝试执行的操作类似的操作,并确保Ben的示例中的陷阱代码无法与它们一起编写。
同时,您当然可以做类似的事情
private static void PrintAll<T>(IEnumerable<T> list)
{
foreach (var item in list)
{
Console.WriteLine(item.ToString());
}
}
static void Main()
{
List<int> numbers = Enumerable.Range(1, 10).ToList();
PrintAll(numbers);
}
这是获得协方差的好方法。 此外,您可以使用where子句将PrintAll的通用参数限制为方便的基类。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.