C# 这是什么财产?有必要吗?

C# 这是什么财产?有必要吗?,c#,nhibernate,C#,Nhibernate,创建映射时,我了解到您的集合属性应该如下所示: public virtual ReadOnlyCollection<Product> Products { get { return new ReadOnlyCollection<Product>(new List<Product>(_products).AsReadOnly()); } } 公共虚拟只读集合产品 { 获取{return new ReadOnlyCollecti

创建映射时,我了解到您的集合属性应该如下所示:

  public virtual ReadOnlyCollection<Product> Products
  {
           get { return new ReadOnlyCollection<Product>(new List<Product>(_products).AsReadOnly()); }
  }
公共虚拟只读集合产品
{
获取{return new ReadOnlyCollection(新列表(_products).AsReadOnly());}
}

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

我认为它建议这样构建它,这样您就不能修改调用代码中的列表。通常,您可以操作它(因为它将通过引用传递)——添加项、删除项等。这确保您必须使用setter来更改内部列表

我不会说它必须是这样的,除非您希望getter返回只读列表。

它返回一个包装类实例,阻止调用方直接修改您返回的集合

如果只返回基础列表,则任何调用方都可以以可能破坏实际拥有该列表的类的方式对其进行更改

即使您以只读接口(比如IEnumerable或ICollection)返回列表,也没有什么可以阻止调用方执行运行时强制转换并获取列表

通过返回包装器对象,可以防止调用方更改列表。包装器不公开任何允许更改基础列表的方法,尝试转换包装器对象将失败。包装器不会复制数据-它只保留对列表的引用,并防止写入操作


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

它特别返回一个不能修改的新集合。看起来有点傻。除非我弄错了,否则可能是:

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

这个代码对我来说似乎是多余的。。。为什么不干脆
退货\u products.AsReadOnly()
?(假设_products是一个
列表、数组或任何公开
AsReadOnly
方法的类型)

您的代码看起来有点奇怪。首先,它创建了_产品的一个副本,然后使其成为只读,然后再次将其包装在ReadOnlyCollection中

如果要公开应为只读的集合,请执行以下操作:

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

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

public ReadOnlyCollection<Product> Products
{
    get
    {
        return _readonlyProducts;
    }
}
private List_products=new List();
私有只读集合\u只读产品=
新的只读集合(_产品);
公共只读收集产品
{
得到
{
返回只读产品;
}
}
无需每次重新创建ReadOnlyCollection(或复制或双重包装集合)。

您的集合不必总是只读的。这完全取决于该列表的用途。如果它实际上只是一个用于引用的列表,那么您甚至可以返回
IEnumerable
,而不是
ReadOnlyCollection
,除非您明确需要一个只读集合

要使其成为只读集合,我将执行以下操作:

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

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

不过,我还是会打电话给
AsReadOnly
,因为我认为在内部它会为您整理列表。

我想
\u products
ICollection
IEnumerable
——在这种情况下,我认为有
新列表(\u products.AsReadOnly()
)就足够了。 如果
\u products
IList
,那么
新的只读集合(\u products)
就足够了。
是否使用此选项取决于类的设计-在某些情况下,最好返回集合适配器,将每个产品隐藏到只读ProductView或ProductDTO实例中。

因此,它本质上是确保您不尝试从映射的“末端”更改列表,您必须在设置cascade=update/save/etc和inverse=false的末尾对其进行修改?是的。这是一种控制访问点的方法,通过它可以更改集合。
private List<Product> products = new List<Product>();

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