这是什么样的属性?有必要吗?

问题描述:

当创建一个映射,我读您的收藏属性应该是这样的:这是什么样的属性?有必要吗?

public virtual ReadOnlyCollection<Product> Products 
    { 
      get { return new ReadOnlyCollection<Product>(new List<Product>(_products).AsReadOnly()); } 
    } 

为什么一定要这样?它每次被引用时似乎都会返回一个新的集合?

它返回一个包装类实例,它阻止调用者能够直接修改您要返回的集合。

如果你简单地返回底层列表,任何调用者将能够改变它可能破坏实际上拥有列表中的类方法。

即使您将列表作为只读接口(例如IEnumerable或ICollection)返回,也不会阻止调用方执行运行时转换并获取列表。

通过返回一个包装对象,可以防止调用者有史以来能够改变列表。包装不会公开任何允许更改底层列表的方法,并且试图转换包装器对象将失败。包装器不复制数据 - 它只是保持对列表的引用,并防止写入操作。

对于ORM映射,这允许对象模型控制在哪个访问点可以更改对象之间的关系。

+0

所以它基本上确保你不会尝试和改变映射的这个'结束'列表,你必须改变它在你已经设置cascade = update/save/etc.和inverse =假? – mrblah 2010-01-13 15:03:37

+1

是的。这是一种控制访问点的方法,通过它可以更改集合。 – LBushkin 2010-01-13 15:04:56

我相信它建议像这样构建它,所以你不能修改调用代码中的列表。通常你可以操作它(因为它会通过引用传递) - 添加项目,删除项目等。这确保你必须使用setter来更改内部列表。

我不会说它就像那样,除非你想让你的getters返回只读列表。

它具体返回一个无法修改的新集合。似乎有点愚蠢,但。除非我记错了,则可能是:

public virtual ReadOnlyCollection<Product> Products 
{ 
    get 
    { 
     return new List<Product>(_products).AsReadOnly(); 
    } 
} 

,或者,如果_products是某种List<Product>已经:

public virtual ReadOnlyCollection<Product> Products 
{ 
    get 
    { 
     return _products.AsReadOnly(); 
    } 
} 

此代码似乎是多余的,我...为什么不return _products.AsReadOnly()? (假设_products是一个List<T>,阵列或任何暴露了AsReadOnly方法的类型)

您的代码看起来有点奇怪。首先它创建一个_products的副本,然后使其只读,然后将其重新包装在ReadOnlyCollection中!

如果要公开应该是只读的,做这样的事情的集合:

private List<Product> _products = new List<Product>(); 

private ReadOnlyCollection<Product> _readonlyProducts = 
    new ReadOnlyCollection(_products); 

public ReadOnlyCollection<Product> Products 
{ 
    get 
    { 
     return _readonlyProducts; 
    } 
} 

无需每次重新创建ReadOnlyCollection(或复制或或双卷集)。

您的收藏不包含已将设为永远只读。这取决于列表的具体内容。如果它实际上只是一个引用列表,那么除非您明确需要只读集合,否则您甚至可以返回IEnumerable而不是ReadOnlyCollection

要使它成为一个只读集合,我会做:

private List<Product> products = new List<Product>(); 

public ReadOnlyCollection<Product> Products { get { return products.AsReadOnly(); } } 

没有必要用new ReadOnlyCollection语句来包裹AsReadOnly方法。或者你可以这样做:

public ReadOnlyCollection<Product> Products { get { return new ReadOnlyCollection<Product>(products); } } 

不过,我只是呼吁AsReadOnly去,因为我想在内部它只是无论如何包装列表为你。

我想_productsICollection<Product>IEnumerable<Product> - 在这种情况下,我认为这是足够有new List<Product>(_products).AsReadOnly()。 如果_products是​​那么new ReadOnlyCollection<Product>(_products)就足够了。 是否使用这个决定取决于类的设计 - 在某些情况下,将每个产品隐藏的收集适配器返回到只读ProductView或ProductDTO实例甚至更好。