C# 集合内引用类型的封装
我声明了一个具有多个属性的类C# 集合内引用类型的封装,c#,collections,encapsulation,indexer,C#,Collections,Encapsulation,Indexer,我声明了一个具有多个属性的类 class Soil { public double AnglePhi { get; set; } public double AngleDelta { get; set; } . . . } 现在为了操纵它们的集合,我构建了另一个专用类,只是出于这个原因 class Soils { private const Byte numberOPredefined = 10; private IList<Soil> soils
class Soil
{
public double AnglePhi { get; set; }
public double AngleDelta { get; set; }
.
.
.
}
现在为了操纵它们的集合,我构建了另一个专用类,只是出于这个原因
class Soils
{
private const Byte numberOPredefined = 10;
private IList<Soil> soils;
public Soil this[ushort i]
{
get { return new Soil() { AngleDelta = soils[i].AngleDelta, ... }; }
set { if (i > numberOPredefined) soils[i] = value; }
}
.
.
.
}
这背后的逻辑是在某种程度上保护每个土壤实例的属性不受直接操纵。在getter中提供一个副本,在setter中请求一个完整的土壤对象
根据我目前所了解的情况,其他解决方案可以是:
使土壤类别不变,
返回一个只读列表,但是可以操作IDE中的引用类型
将“土壤类别”转换为“结构简单”,
用一些逻辑方法等扩充土壤类
我想问一下,上述解决方案是否有任何价值,或者定义不清
我认为这是一种典型的情况,例如拥有一组引用类型并希望封装它们。在这些情况下,典型的思维框架是什么
编辑:
好的,在阅读了答案之后,我修改了这个问题的解决方案
class Soil
{
private readonly double _AnglePhi;
public double AnglePhi { get { return _AnglePhi; } }
private readonly double _AngleDelta;
public double AngleDelta { get { return _AngleDelta; } }
.
.
}
class SoilCollection
{
private List<Soil> _Soils;
public IList<Soil> Soils { get { return _Soils.AsReadOnly(); } }
.
.
}
我认为土壤类需要它内部的逻辑,而不是另一个类内部的逻辑。如果我发现任何不足之处,我将发布。您可以将土壤定义为ValueObject,那么它在创建后将是不可变的:
class Soil
{
public Soil(double anglePhi, double angleDelta)
{
AnglePhi = anglePhi;
AngleDelta = angleDelta;
}
public double AnglePhi { get; private set; }
public double AngleDelta { get; private set; }
}
我认为最好将土壤重命名为SoilCollection。您可以将土壤定义为ValueObject,那么它在创建后将是不可变的:
class Soil
{
public Soil(double anglePhi, double angleDelta)
{
AnglePhi = anglePhi;
AngleDelta = angleDelta;
}
public double AnglePhi { get; private set; }
public double AngleDelta { get; private set; }
}
我认为最好将Soil重命名为SoilCollection。没有理由在Soil类上同时实现setter和getter。您可以选择仅实现get,这将使土壤对象成为只读对象 显然,您必须使用其他一些方法来设置内部值——这可以在构造函数中完成 例如:
class Soil
{
private double m_anglePhi;
public Soil( double anglePhi )
{
m_anglePhi = anglePhi;
}
public double AnglePhi
{
get { return m_anglePhi; }
}
}
没有理由在土壤类上同时实现setter和getter。您可以选择仅实现get,这将使土壤对象成为只读对象 显然,您必须使用其他一些方法来设置内部值——这可以在构造函数中完成 例如:
class Soil
{
private double m_anglePhi;
public Soil( double anglePhi )
{
m_anglePhi = anglePhi;
}
public double AnglePhi
{
get { return m_anglePhi; }
}
}
如果希望土壤类型具有复制语义,请将其定义为结构。然后,通过将支持字段声明为只读并添加适当的构造函数,应该使其不可变
struct Soil
{
private readonly double anglePhi;
private readonly double angleDelta;
public Soil(double phi, double delta) {
this.anglePhi = phi;
this.angleDelta = delta;
}
public double AnglePhi { get { return anglePhi; } }
public double AngleDelta { get { return angleDelta; } }
}
若您将其保留为类,我不会使用索引器来检索对象的副本。我宁愿使用一种方法来明确用户正在获取对象的副本。并将其设置为只读,就像上面的结构一样,就像类一样。这可能也会消除复制的需要 如果希望土壤类型具有复制语义,请将其定义为结构。然后,通过将支持字段声明为只读并添加适当的构造函数,应该使其不可变
struct Soil
{
private readonly double anglePhi;
private readonly double angleDelta;
public Soil(double phi, double delta) {
this.anglePhi = phi;
this.angleDelta = delta;
}
public double AnglePhi { get { return anglePhi; } }
public double AngleDelta { get { return angleDelta; } }
}
若您将其保留为类,我不会使用索引器来检索对象的副本。我宁愿使用一种方法来明确用户正在获取对象的副本。并将其设置为只读,就像上面的结构一样,就像类一样。这可能也会消除复制的需要 我建议:
1使土壤类别不可变
2使土壤成为a类只读集合。
与中一样,从IList派生并声明add etc方法作为interfact的显式实现。我建议:
1使土壤类别不可变
2使土壤成为a类只读集合。
如中所述,从IList派生并将add-etc方法声明为interfact的显式实现。但如前所述,类中有多个属性,这违反了保持结构小的原则。但如前所述,类中有多个属性,这违反了保持结构小型化的原则。你是指这个链接所解释的ValueObject吗?嗯,我没有读整篇文章,但是是的,根据title-Value,对象是对象,其标识基于它们的状态,而不是它们在内存中的指针。不可变值对象是不能更改的值对象。你不能修改它的状态,你必须创建新的状态。你是说这个链接解释的ValueObject吗?嗯,我没有读整篇文章,但是是的,根据title-Value,对象是对象,其标识基于它们的状态,而不是它们在内存中的指针。不可变值对象是不能更改的值对象。你不能修改它的状态,你必须创建新的状态。谢谢你的回答,Amby。谢谢你的回答,Amby。