[英]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.