C# 无法从列表转换<;DerivedClass>;列出<;基类>;
我试图将C# 无法从列表转换<;DerivedClass>;列出<;基类>;,c#,C#,我试图将DerivedClass列表传递给一个函数,该函数获取BaseClass列表,但出现错误: cannot convert from 'System.Collections.Generic.List<ConsoleApplication1.DerivedClass>' to 'System.Collections.Generic.List<ConsoleApplication1.BaseClass>' 无法从转换 'System.Collections.Ge
DerivedClass
列表传递给一个函数,该函数获取BaseClass
列表,但出现错误:
cannot convert from
'System.Collections.Generic.List<ConsoleApplication1.DerivedClass>'
to
'System.Collections.Generic.List<ConsoleApplication1.BaseClass>'
无法从转换
'System.Collections.Generic.List'
到
'System.Collections.Generic.List'
现在,我可以将我的列表
转换为列表
,但除非我理解编译器为什么不允许这样做,否则我不会感到舒服
我发现的解释只是说它在某种程度上违反了类型安全性,但我没有看到它。有人能帮我吗
编译器允许从列表
转换到列表
,有什么风险
这是我的SSCCE:
class Program
{
public static void Main()
{
BaseClass bc = new DerivedClass(); // works fine
List<BaseClass> bcl = new List<DerivedClass>(); // this line has an error
doSomething(new List<DerivedClass>()); // this line has an error
}
public void doSomething(List<BaseClass> bc)
{
// do something with bc
}
}
class BaseClass
{
}
class DerivedClass : BaseClass
{
}
类程序
{
公共静态void Main()
{
BaseClass bc=新的DerivedClass();//工作正常
List bcl=new List();//此行有错误
doSomething(new List());//此行有错误
}
公共无效剂量测定(列表bc)
{
//用bc做点什么
}
}
类基类
{
}
类派生类:基类
{
}
您描述的行为称为协方差–如果A
是B
,则List
是List
但是,对于像List
这样的可变类型,这从根本上说是不安全的
如果这是可能的,该方法将能够将一个新的OtherDerivedClass()
添加到一个实际上只能保存DerivedClass
的列表中
协方差在不可变类型上是安全的,尽管.Net仅在接口和委托中支持协方差。如果将
List
参数更改为IEnumerable
,则该参数将起作用,因为List
在variant中是,而不是co variant
,因此应更改为支持co variant
的IEnumerable
,该参数应起作用:
IEnumerable<BaseClass> bcl = new List<DerivedClass>();
public void doSomething(IEnumerable<BaseClass> bc)
{
// do something with bc
}
IEnumerable bcl=new List();
公共无效剂量测定(IEnumerable bc)
{
//用bc做点什么
}
关于的信息,如果你能写
List<BaseClass> bcl = new List<DerivedClass>();
将非DerivedClass的实例添加到列表中。当您有一个从基类派生的类时,这些类的任何容器都不会自动派生。因此,您不能将列表
强制转换为列表
使用.Cast()
创建一个新列表,其中每个对象都被强制转换回基类:
List<MyDerived> list1 = new List<MyDerived>();
List<MyBase> list2 = list1.Cast<MyBase>().ToList();
List list1=新列表();
List list2=list1.Cast().ToList();
请注意,这是一个新列表,而不是原始列表的强制转换版本,因此此新列表上的操作不会反映在原始列表上。但是,对包含对象的操作将反映
我发现的解释只是说它在某种程度上违反了类型安全性,但我没有看到它。编译器允许从列表
转换到列表
,有什么风险
这个问题几乎每天都有人问
列表
无法转换为列表
,因为可以将蜥蜴放入动物列表中。列表无法转换为列表
,因为列表中可能已经有老虎
因此,List
必须在T中保持不变
但是,List
可以转换为IEnumerable
(从C#4.0开始),因为在IEnumerable
上没有添加蜥蜴的方法IEnumerable
在T中是协变的。我使用的解决方案是创建一个扩展类:
public static class myExtensionClass
{
public void doSomething<T>(List<BaseClass> bc) where T: BaseClass
{
// do something with bc
}
}
公共静态类myExtensionClass
{
公共无效剂量仪(列表bc),其中T:基类
{
//用bc做点什么
}
}
它使用泛型,但当您调用它时,您不必指定类,因为您已经“告诉”编译器类型与扩展类相同
你可以这样称呼它:
List<DerivedClass> lst = new List<DerivedClass>();
lst.doSomething();
List lst=new List();
l.剂量测定法();
类从它的基派生,而不是列表
从列表
派生@TimSchmelter这是否意味着这种继承可能成为一种特性,其中泛型
可以被视为从泛型
派生?或者这样的功能会导致问题吗?只是没有这样实现@蒂姆施梅尔特:不;这样做是不可能的。@SamIam:您应该先将其实例化为一个列表
。@SamIam:不;您正试图传递一个列表
。传递一个包含派生的的列表
会很好。因此,如果我在传递前将列表
转换为列表
,那可以吗?@SamIam:不可以。关键是将列表
转换为列表
,从根本上说是不安全的。如果您首先创建一个列表
,它会起作用。@SamIam:SLaks解释得很好:如果您可以将列表
强制转换为列表
,那么理论上您可以将其他派生的
的实例添加到该列表中(因为该列表是可变的)。但是它被实例化为一个列表
,如果您试图手动将其转换回列表
,您将得到一个列表
,其中包含一个其他派生的
。从.Net 4.5开始,如果方法需要随机访问集合元素,也可以使用IReadOnlyList
。+1一个简单的动物学解释解释了这一切。(IEnumerable上没有添加蜥蜴-->的方法,我会检查以防万一;))我觉得自己很笨。。。长颈鹿似乎很明显,但为什么你不能把哺乳动物传给能对付动物的东西,仅仅因为它也能对付非哺乳动物呢?@MGOwen:你有一个哺乳动物的列表。你决定把它当作一个动物列表。你把一只蜥蜴列入动物名单。但它实际上是一个哺乳动物的列表。现在你有了一个包含蜥蜴的哺乳动物列表,违反了哺乳动物列表中只有mam的预期
List<DerivedClass> lst = new List<DerivedClass>();
lst.doSomething();