我有以下课程:
class SampleClass
{
private ArrayList mMyList;
SampleClass()
{
// Initialize mMyList
}
public ArrayList MyList
{
get { return mMyList;}
}
}
我希望用户能够获得mMyList,这就是我通过属性暴露“get”的原因,但是我不希望他们对该对象做出更改(即。MyList.Add(new Class());)回到我的班级。
我想我可以返回对象的副本,但这可能很慢,我正在寻找一种方法,它会提供编译时错误,通知用户他们不应该期望能够修改返回的该物业的价值。
这可能吗?
答案 0 :(得分:25)
使用ArrayList你是相当有限的,因为BCL中没有readonly非泛型集合类。快速而肮脏的解决方案是返回一种IEnumerable。
public IEnumerable MyList
{
get { return mMyList;}
}
这实际上不会阻止某人转换为ArrayList,但默认情况下不允许编辑
您可以通过调用ArrayList.ReadOnly返回有效的只读列表。但是它的返回类型是一个ArrayList,因此用户仍然可以使用.Add编译,但它会产生运行时错误。
答案 1 :(得分:19)
使用ArrayList.ReadOnly()方法构造并返回列表周围的只读包装器。它不会复制列表,而只是围绕它创建一个只读包装器。为了获得编译时检查,您可能希望将只读包装器作为@nared建议的IEnumerable返回。
public IEnumerable MyList
{
get { return ArrayList.ReadOnly(mMyList); }
}
只读的集合是 只是一个包装的集合 这会阻止修改 采集。如果对此进行了更改 底层集合,只读 集合反映了这些变化。
此方法是O(1)操作。
答案 2 :(得分:9)
只是为了扩展JaredPar的答案。正如他所说,返回实际的支持字段并不完全安全,因为用户仍然可以动态地将IEnumerable
转换回ArrayList
。
我会写这样的东西,以确保不会对原始列表进行任何修改:
public IEnumerable MyList
{
get
{
foreach (object o in mMyList)
yield return o;
}
}
然后,我可能会使用通用列表(IEnumerable<T>
)完全是类型安全的。
答案 3 :(得分:4)
使用ReadOnlyCollection
。
return new ReadOnlyCollection<object>(mMyList)
。
您还可以将ReadOnlyCollection
字段设为一个字段,它会自动反映基础列表中的更改。这是最有效的解决方案。
如果你知道mMyList只包含一种类型的对象(例如,它只有DateTimes),
您可以返回ReadOnlyCollection<DateTime>
(或其他类型)以获得额外的类型安全性。如果您使用的是C#3,则只需编写
return new ReadOnlyCollection<DateTime>(mMyList.OfType<DateTime>().ToArray())
但是,这不会自动更新基础列表,效率也会降低(它会复制整个列表)。最好的选择是使mMyList成为通用List<T>
(例如,List<DateTime>
)
答案 4 :(得分:4)
答案 5 :(得分:1)
您应该将返回值包装在只读集合中。
答案 6 :(得分:0)
可从.NET v2.0
获取 public ArrayList MyList { get; private set; }
答案 7 :(得分:-3)
只需将属性设置为Sealed(或VB.NET中的NotInheritable),并且只读取,如下所示:
public sealed readonly ArrayList MyList
{
get { return mMyList;}
}
另外,不要忘记将支持字段设为只读:
private readonly ArrayList mMyList;
但是为了初始化mMyList的值,您必须仅在构造函数中初始化它,如下例所示:
public SampleClass()
{
// Initialize mMyList
mMyList = new ArrayList();
}