2011-02-08 71 views
14

考慮以下幾種類型:鑄造名單<T> - 協方差/逆變問題

public interface IMyClass { } 
public class MyClass : IMyClass { } 

我不知道如何可以轉換List<MyClass>List<IMyClass>?我並不完全清楚協變性/逆變性話題,但是我明白我不能因爲這個而清楚地列出這個列表。

我可以想出這個微不足道的解決方案;缺乏任何高雅,浪費資源:

... 
public List<IMyClass> ConvertItems(List<MyClass> input) 
{ 
    var result = new List<IMyClass>(input.Count); 
    foreach (var item in input) 
    { 
     result.Add(item); 
    } 
    return result; 
} 
.... 

你怎麼能解決它更優雅/性能方法?

請記住,我需要.NET 2.0的解決方案,但爲了完整,我會很樂意使用新版本的框架,也看到了更多的優雅的解決方案。

回答

21

最簡單的方法可能是使用ConvertAll:即使你使用.NET 2

List<IMyClass> converted = original.ConvertAll<IMyClass>(x => x); 

,你可以,如果你正在使用VS2008或更高的使用lambda語法。否則,總有匿名方法:

List<IMyClass> converted = original.ConvertAll<IMyClass>(
    delegate (MyClass x) { return x; }); 

在.NET 3.5,你可以用CastOfType甚至只是Select使用LINQ:

var converted = original.Cast<IMyClass>().ToList(); 
var converted = original.OfType<IMyClass>().ToList(); 
var converted = original.Select(x => (IMyClass) x).ToList(); 

在.NET 4.0中,你可以直接使用ToList沒有中間由於IEnumerable<T>的協方差:

var converted = original.ToList<IMyClass>(); 
+0

這是一種偷偷使用的協方差;非常好。 – Ani 2011-02-08 10:25:52

0

(.NET 3.5解決方案)

List<MyClass> list = new List<MyClass> { ... }; 
List<IMyClass> converted = list.Cast<IMyClass>().ToList(); 
+0

轉換是`IEnumerable `而不是`列表` – CodesInChaos 2011-02-08 10:42:47

+0

@CodeInChaos:對不起,什麼? – abatishchev 2011-02-08 16:11:13

1

是否需要列表? IEnumerable解決方案可能更有效率:

public IEnumerable<IMyClass> ConvertItems(List<MyClass> input) 
{ 
    foreach (var item in input) 
    { 
     yield return (IMyClass)item; 
    } 
}