public interface IDic
{
int Id { get; set; }
string Name { get; set; }
}
public class Client : IDic
{
}
如何将List<Client>
投射到List<IDic>
?
答案 0 :(得分:205)
你不能施放它(保留参考标识) - 这是不安全的。例如:
public interface IFruit {}
public class Apple : IFruit {}
public class Banana : IFruit {}
...
List<Apple> apples = new List<Apple>();
List<IFruit> fruit = apples; // Fortunately not allowed
fruit.Add(new Banana());
// Eek - it's a banana!
Apple apple = apples[0];
现在,由于协方差,您可以在.NET 4 / C#4中将List<Apple>
转换为IEnumerable<IFruit>
,但如果您想要List<IFruit>
,则必须创建新列表。例如:
// In .NET 4, using the covariance of IEnumerable<T>
List<IFruit> fruit = apples.ToList<IFruit>();
// In .NET 3.5
List<IFruit> fruit = apples.Cast<IFruit>().ToList();
但这不与投射原始列表相同 - 因为现在有两个单独的列表。这是安全的,但您需要了解对一个列表所做的更改不会在另一个列表中看到。 (当然,将会看到列表引用的对象的修改。)
答案 1 :(得分:5)
Cast iterator和.ToList():
List<IDic> casted = input.Cast<IDic>().ToList()
可以解决问题。
最初我说协方差会奏效 - 但正如乔恩正确指出的那样;不,它不会!
最初我还愚蠢地离开了ToList()
电话
答案 2 :(得分:4)
我也有这个问题,在阅读Jon Skeet的回答后,我修改了我的代码,使用List<T>
来使用IEnumerable<T>
。虽然这不符合OP的原始问题如何将List<Client>
投射到List<IDic>
,但它确实避免了这样做,因此可能会有所帮助对遇到此问题的其他人。当然,这假定需要使用List<IDic>
的代码由您控制。
E.g:
public void ProcessIDic(IEnumerable<IDic> sequence)
{
// Implementation
}
而不是:
public void ProcessIDic(List<IDic> list)
{
// Implementation
}
答案 3 :(得分:2)
如果您可以使用LINQ,那么您可以这样做......
List<Client> clientList = new List<Client>();
List<IDic> list = clientList.Select(c => (IDic)c).ToList();
答案 4 :(得分:2)
List<Client> listOfA = new List<Client>();
List<IDic> list = listOfA.Cast<IDic>().ToList();
答案 5 :(得分:0)
只有通过创建新的List<IDic>
并传输所有元素才能实现。
答案 6 :(得分:0)
在.Net 3.5中,您可以执行以下操作:
List<ISomeInterface> interfaceList = new List<ISomeInterface>(list.Cast<ISomeInterface>());
在这种情况下,List的构造函数采用IEnumerable。
列表虽然只能转换为IEnumerable。即使 myObj 可以转换为ISomeInterface,IEnumerable类型也无法转换为IEnumerable。
答案 7 :(得分:0)
您可以尝试类似的操作:
using (var dbContext = YourDatabaseContext())
{
var list = dbContext.Clients.Where(x => x.Happy)
.OfType<IDic>()
.ToList();
}
请参见https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.oftype