我注意到了一些奇怪的事情,有可能我错了。
我有一个接口(interface)IA和A类:

interface IA { .... }
class A : IA { .... }

在其他类(class),我有这个:
private IList<A> AList;

public IList<IA> {
    get { return AList; }
}

但是我得到编译错误。
但是,如果我将其更改为:
public IList<IA> {
    get { return AList.ToArray(); }
}

一切安好。

为什么?

最佳答案

为什么这不起作用

private IList<A> AList;
public IList<IA> { get { return AList; } }

将属性公开为IList<IA>可以使您尝试将class B : IA添加到列表中,但是基础列表实际上是IList<A>B不是A,因此这会在您的面前大发雷霆。因此,这是不允许的。

工作原理:
public IList<IA> { get { return AList.ToArray(); } }

数组方差被打破。您可以将列表作为数组返回,如果您尝试了Add操作(或者尝试用A类型的对象以外的对象替换给定索引处的对象),它在运行时仍会在您的面前炸毁。编译时。这种差异在起作用的另一个示例:
string[] array = new string[10];
object[] objs = array; // legal
objs[0] = new Foo(); // will bite you at runtime

来自评论:



如果使用者只需要遍历该序列,而没有对它的随机索引访问,则可以将该属性公开为IEnumerable<IA>
public IEnumerable<IA> TheList
{
     get { return AList.Select(a => a); }
}

(实际上在技术上并不需要Select,但是使用此方法将阻止使用者将结果强制转换为其真正的基础List<>类型。)如果使用者决定要使用列表或数组,则可以自由调用ToList()ToArray()。对其进行任何操作(就添加,删除,替换项目而言)都不会影响您的列表。 (对项目属性的更改将是可见的。)同样,您也可以自己以安全的方式向集合公开IList<IA>
public IList<IA> TheList
{
    get { return AList.ToList<IA>(); }
}

同样,这将返回列表的副本,因此对其所做的任何更改都不会影响您的基础列表。

关于c# - list.ToArray与lis,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6750751/

10-13 03:28