Инкапсуляция ссылочных типов внутри коллекции - PullRequest
1 голос
/ 21 января 2011

Я объявил класс с несколькими свойствами

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; }
  }
  .
  .
  .
}

Логика, стоящая за этим, заключается в некоторой защите от прямого манипулирования свойствами каждого экземпляра Soil.Дайте копию в getter, попросите «целый» объект почвы в setter.

Из того, что я до сих пор читал, могут быть другие решения:
сделать класс почвы неизменным,
вернуть список ReadOnly(но тогда можно манипулировать ссылочными типами внутри).
превратить класс Soil в struct (simple),
дополнить класс Soil некоторой логикой (методами и т. д.).

Я хотел бы спросить, имеет ли вышеуказанное «решение» какое-либо значение или оно плохо определено.

Это типичная ситуация, я думаю, например, имея коллекцию ссылочных типов и хочу инкапсулировать их .Каков типичный образ мышления в этих ситуациях?

РЕДАКТИРОВАТЬ:
Хорошо, после прочтения ответов я изменил решение для этого

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(); } }
  .
  .
}

Я думаю, что классу Soil нужна логика внутри него, а невнутри другой класс.Я опубликую, если найду какие-либо недостатки.

Ответы [ 4 ]

2 голосов
/ 21 января 2011

Если вы хотите, чтобы ваш тип почвы имел семантику копирования, определите его как структуру. Затем вы должны сделать его неизменным, объявив вспомогательные поля только для чтения и добавив соответствующий конструктор.

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; } }
}

Если вы сохраните его как класс, я бы не использовал индексатор для получения копий объектов. Я бы предпочел использовать метод, чтобы понять, что пользователь получает копию объекта. И сделайте его доступным только для чтения, как структура выше, так же, как класс. Это, вероятно, также избавит от необходимости делать копии.

2 голосов
/ 21 января 2011

Вы можете определить Почву как 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.

1 голос
/ 21 января 2011

я бы предложил:

1) Сделать класс почвы неизменным.

2) Сделать класс почвы почтой только для чтения.Например, унаследовать от IList и объявить методы add и т.д. как явную реализацию interfact.

1 голос
/ 21 января 2011

Нет причин, по которым вам нужно внедрять и метод установки, и метод получения в классе Soil. Вы можете выбрать только реализацию get, которая сделает объекты Soil доступными только для чтения.

Очевидно, вам понадобится какой-то другой метод задания внутренних значений - это можно сделать в конструкторе.

Например:

class Soil
{
    private double m_anglePhi;

    public Soil( double anglePhi )
    {
        m_anglePhi = anglePhi;
    }

    public double AnglePhi 
    {
        get { return m_anglePhi; }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...