Нужно группу экземпляров отсылать на одно и тот же поле
Описание
Есть у меня некий класс Limiter
:
class Limiter
{
public uint Index = 0;
public Limiter GetSublimiter()
{
Limiter sublimiter = new();
return sublimiter;
}
}
Как видите она может создать себе подобных через метод GetSublimiter
. Мне надо сделать так, чтобы у каждого экземпляра, созданный через GetSublimiter
Index отсылался на тот же Index что и у "родителя". То есть:
static void Main(string[] args)
{
Limiter limiter1 = new(); // limiter1.Index: 0
Limiter sublimiter11 = limiter1.GetSublimiter(); // limiter1.Index: 0, sublimiter11.Index: 0
sublimiter11.Index++; // limiter1.Index: 1, sublimiter11.Index: 1
Limiter limiter2 = new(); // limiter2.Index: 0, limiter1.Index: 1, sublimiter11.Index: 1
}
Обратите внимание что Index у limiter1
и limiter2
разные, так как они созданы через конструктор, а не GetSublimiter
.
Вопрос
Собственно какие варианты есть?
Дополнительно
Пытался вот так:
class Limiter
{
public ref uint Index = 0;
public Limiter GetSublimiter()
{
Limiter sublimiter = new();
sublimiter.Index = ref this.Index;
return sublimiter;
}
}
Получил:
A ref field can only be declared in a ref struct.
Ответы (3 шт):
Распространённое решение для такой задачи - это свойства Owner и Parent.
Parent указывает на объект, в который вложен текущий объект, а Owner указывает на самый верхний объект в этой иерархии.
Через эти свойства вы можете получить доступ к свойствам вышестоящих объектов, например, к свойству Index.
Сделать такой механизм в определениях типов не получится.
Это может быть закодировано примерно так:
class Limiter
{
public Limiter Owner { get; init; }
public Limiter Parent { get; init; }
uint _index = 0;
public Limiter()
{
Owner = Parent = null;
}
private Limiter(Limiter limiter)
{
Owner = limiter.Owner; Parent = limiter;
}
public Limiter GetSublimiter() => new Limiter(this);
public uint Index => Owner?.Index ?? _index;
}
Ну может сохранять ссылку на родителя и дальше смотреть - если есть родитель, то обращаемся к индексу родителя, если нет родителя, то обращаемся к собственному индексу.
class Limiter
{
private Limiter? _parent = null;
private uint _index = 0;
public Limiter(Limiter? parent = null)
{
_parent = parent;
}
public Limiter GetSublimiter()
{
Limiter sublimiter = new(this);
return sublimiter;
}
private void SetIndex(uint value)
{
if (_parent is null)
{
_index = value;
}
else
{
_parent.Index = value;
}
}
public uint Index
{
get => _parent?.Index ?? _index;
set => SetIndex(value);
}
}
Сделать класс-обёртку для индекса.
class Limiter
{
private IndexWrapper index;
public Limiter()
{
index = new IndexWrapper();
}
public Limiter GetSublimiter()
{
Limiter sublimiter = new() { index = this.index };
return sublimiter;
}
public uint Index
{
get { return index.Value; }
set { index.Value = value; }
}
private class IndexWrapper
{
public uint Value;
}
}