创建映射时,我正在读取您的集合属性应如下所示:
public virtual ReadOnlyCollection<Product> Products
{
get { return new ReadOnlyCollection<Product>(new List<Product>(_products).AsReadOnly()); }
}
为什么必须这样?它似乎每次被引用时都会返回一个新的集合?
答案 0 :(得分:7)
它返回一个包装类实例,阻止调用者直接修改你要返回的集合。
如果您只是简单地返回基础列表,任何调用者都可以以可能破坏实际拥有列表的类的方式更改它。
即使您将列表作为只读接口(例如IEnumerable或ICollection)返回,也不会阻止调用者执行运行时转换并进入列表。
通过返回包装器对象,可以防止来自的调用者能够更改列表。包装器不公开任何允许更改基础列表的方法,并且尝试转换包装器对象将失败。包装器不会复制数据 - 它只是保留对列表的引用,并阻止写操作。
在ORM映射的情况下,这允许对象模型控制在哪个访问点可以改变对象之间的关系。
答案 1 :(得分:4)
你的代码看起来有点奇怪。首先它创建一个_products的副本,然后它使它只读,然后再将它包装在ReadOnlyCollection中!
如果要公开应该是只读的集合,请执行以下操作:
private List<Product> _products = new List<Product>();
private ReadOnlyCollection<Product> _readonlyProducts =
new ReadOnlyCollection(_products);
public ReadOnlyCollection<Product> Products
{
get
{
return _readonlyProducts;
}
}
每次都不需要重新创建ReadOnlyCollection(或复制或复制或复制集合)。
答案 2 :(得分:2)
您的馆藏不 始终只读。这取决于列表的确切内容。如果它实际上只是一个引用列表,那么你甚至可以返回IEnumerable
而不是ReadOnlyCollection
,除非你明确需要一个只读集合。
为了使它成为一个只读集合,我会这样做:
private List<Product> products = new List<Product>();
public ReadOnlyCollection<Product> Products { get { return products.AsReadOnly(); } }
无需使用AsReadOnly
语句包装new ReadOnlyCollection
方法。或者你可以这样做:
public ReadOnlyCollection<Product> Products { get { return new ReadOnlyCollection<Product>(products); } }
但是,我只是打电话给AsReadOnly
,因为我认为在内部它只是为你包装你的清单。
答案 3 :(得分:1)
我相信它建议像这样构建它,这样你就无法修改调用代码中的列表。通常你可以操作它(因为它将通过引用传递) - 添加项目,删除项目等。这确保你必须使用setter来更改内部列表。
我不会说 完全相同,除非你希望你的getter返回只读列表。
答案 4 :(得分:0)
它专门返回一个无法修改的新集合。虽然看起来有点傻。除非我弄错了,否则可能是:
public virtual ReadOnlyCollection<Product> Products
{
get
{
return new List<Product>(_products).AsReadOnly();
}
}
或者,如果_products
已经某种List<Product>
:
public virtual ReadOnlyCollection<Product> Products
{
get
{
return _products.AsReadOnly();
}
}
答案 5 :(得分:0)
这段代码对我来说似乎是多余的......为什么不只是return _products.AsReadOnly()
? (假设_products是List<T>
,数组或任何公开AsReadOnly
方法的类型)
答案 6 :(得分:0)
我认为_products
是ICollection<Product>
或IEnumerable<Product>
- 在这种情况下,我认为只有new List<Product>(_products).AsReadOnly()
就足够了。
如果_products
为IList<Product>
,那么new ReadOnlyCollection<Product>(_products)
就足够了。
决定是否使用它取决于类的设计 - 在某些情况下,返回将每个Product隐藏到只读ProductView或ProductDTO实例中的集合适配器会更好。