Страницы

Поиск по вопросам

вторник, 2 апреля 2019 г.

Корректный способ защиты множества объектов от изменений

Нужно написать приложение, которые моделирует некоторые физические процессы. Будет написан некоторый класс Simulation, содержащий основные методы управления процессом моделирования (например метод Step()). Все операции в конечном итоге будут производиться над множеством (HashSet) объектов типа Atom. Над этим множеством после моделирования надо производить различные действия, к классу Simulation не относящиеся (да и перед моделированием это множество надо соорудить отдельно или откуда-то загрузить). В процессе моделирования (то есть пока будет выполняться метод Step()) множество атомов желательно как-то защитить от воздействия извне, т. е. запретить добавление / удаление атомов, изменение их свойств.
Можно сделать HashSet полем класса Simulation, определив так же методы Add(Atom atom), Remove(Atom atom) и т. п. А для защиты изменения в процессе моделирования использовать if (locked) return
public class Simulation { private readonly HashSet _atoms = new HashSet();
. . .
private bool locked;
public bool Add(Atom atom) { if (locked) return false; if (atom == null) throw new ArgumentNullException(nameof(atom)); return _atoms.Add(atom); }
public bool Remove(Atom atom) { if (locked) return false; return _atoms.Remove(atom); }
public void Step(float dt) { locked = true;
. . .
locked = false; }
. . .
}
Но такой подход не позволяет защитить атомы от изменения во время моделирования если ссылки на них есть где-то вне множества _atoms
Подскажите, пожалуйста, как корректно разрешить данную проблему.

EDIT
Атом представляет собой следующий класс:
[Serializable] public class Atom { private static int _numberOfInstances;
[NonSerialized] private readonly int _hashCode;
public Atom() { _hashCode = Interlocked.Increment(ref _numberOfInstances); }
[field: NonSerialized] internal Vector3 Acceleration { get; set; } [field: NonSerialized] internal Vector3 Displacement { get; set; }
public Vector3 Position { get; set; } public Vector3 Velocity { get; set; }
public override int GetHashCode() { return _hashCode; } }
И защищать тут нужно свойства Position и Velocity


Ответ

Вариант 1.
Точно так же, как Вы уже показали. Добавить поле locked в Atom и проверять его во всех сетерах свойств.
Вариант 2.
Склонировать набор атомов в новые объекты, на которые ни у кого нет ссылок, и работать с ними.

Комментариев нет:

Отправить комментарий