Избежать передачи поля дочернего класса в конструктор родительского класса
Есть внешние классы Node1 и Node2 (которые я не могу изменить) и для которых необходимо создать классы-обертки NodeWrapper1 и NodeWrapper2 соответственно
В классе NodeWrapper1 есть поле ID, которое необходимо считать и добавить в список использованных ID
Список использованных ID хранится в поле id_generator (класс IDGenerator) класса NodeListService1
В конструкторе класса NodeListService создается список с классами-обертками с помощью делегата "create_node" (передается через параметр конструктора)
В конструкторе класса NodeListService1 необходимо считать ID с каждого объекта-обертки и добавить в список использованных ID
Это делается с помощью второго цикла по свойству ElementsList
Хотел бы избежать второго цикла по тем же объектам
Если передать поле id_generator в делегат "create_node", то это вызывает ошибку CS0027
Возможно ли добавить использованные ID в id_generator без использования второго цикла?
Код:
class NodeListService<T> where T : NodeWrapper
{
private List<T> lst_node = new();
internal IList<T> ElementsList
{
get => this.lst_node.AsReadOnly();
}
internal NodeListService(List<Node> lst_ext_node, Func<Node, T> create_node)
{
//первый цикл по списку
foreach (Node cur_node in lst_ext_node)
{
T cur_node_wrapper = create_node(cur_node);
this.lst_node.Add(cur_node_wrapper);
}
}
}
class NodeListService1 : NodeListService<NodeWrapper1>
{
private IDGenerator id_generator = new();
internal NodeListService1(List<Node> lst_ext_node) : base
(
lst_ext_node,
cur_node =>
{
NodeWrapper1 cur_node_wrapper = new((Node1)cur_node);
this.id_generator.AddID(cur_node_wrapper.ID);//ошибка CS0027
}
)
{
//можно сделать так, но это будет вторым циклом по тем же узлам
foreach (NodeWrapper1 cur_node_wrapper in this.ElementsList)
{
this.id_generator.AddID(cur_node_wrapper.ID);
}
}
}
class NodeListService2 : NodeListService<NodeWrapper2>
{
internal NodeListService2(List<Node> lst_ext_node) : base(lst_ext_node, cur_node => new NodeWrapper2((Node2)cur_node))
{
}
}
#region Node
//Классы Node, Node1 and Node2 - это внешние классы, которые я не могу изменить
class Node
{
}
class Node1 : Node
{
internal int ID;
internal Node1(int id)
{
this.ID = id;
}
}
class Node2 : Node
{
internal readonly int OtherField;
internal Node2(int other_field)
{
this.OtherField = other_field;
}
}
#endregion
#region NodeWrapper
//Классы NodeWrapper1 и NodeWrapper2 - это классы-обертки для работы с классами Node1 и Node2 соответственно
//Они наследуют от класса NodeWrapper, т.к. им обоим нужен доступ к полю NodeValue
class NodeWrapper
{
protected readonly Node NodeValue;
internal NodeWrapper(Node cur_node)
{
this.NodeValue = cur_node;
}
}
class NodeWrapper1 : NodeWrapper
{
internal readonly int ID;
#region ctor
internal NodeWrapper1(Node1 cur_node) : base(cur_node)
{
this.ID = cur_node.ID;
}
#endregion
}
class NodeWrapper2 : NodeWrapper
{
internal readonly int SomeOtherField;
internal NodeWrapper2(Node2 cur_node) : base(cur_node)
{
this.SomeOtherField = cur_node.OtherField;
}
}
#endregion
class IDGenerator
{
private int counter = 0;
private HashSet<int> hs_used_id = new();
//Если создан новый объект класса Node1 (и NodeWrapper1 для него), то необходимо сгенерировать последовательно возрастающий ID
internal int GetNewID()
{
while (hs_used_id.Contains(this.counter++)) ;
return this.counter;
}
internal bool AddID(int id) => hs_used_id.Add(id);
}
Ответы (1 шт):
По совету Grundy сделал метод OnNodeCreate
Получилось избежать доп. циклов
Код
class NodeListService<T> where T : NodeWrapper, new()
{
private List<T> lst_node = new();
protected virtual T OnNodeCreate(Node node) => new T();
internal NodeListService(List<Node> lst_ext_node)
{
foreach (Node cur_node in lst_ext_node)
{
this.lst_node.Add(this.OnNodeCreate(cur_node));
}
}
}
class NodeListService1 : NodeListService<NodeWrapper1>
{
private IDGenerator id_generator = new();
protected override NodeWrapper1 OnNodeCreate(Node node)
{
NodeWrapper1 cur_node_wrapper = new((Node1)node);
this.id_generator.AddID(cur_node_wrapper.ID);
return cur_node_wrapper;
}
internal NodeListService1(List<Node> lst_ext_node) : base(lst_ext_node)
{
}
}
class NodeListService2 : NodeListService<NodeWrapper2>
{
internal NodeListService2(List<Node> lst_ext_node) : base(lst_ext_node)
{
}
}
#region Node
class Node
{
}
class Node1 : Node
{
internal int ID;
internal Node1(int id)
{
this.ID = id;
}
}
class Node2 : Node
{
internal readonly int OtherField;
internal Node2(int other_field)
{
this.OtherField = other_field;
}
}
#endregion
#region NodeWrapper
class NodeWrapper
{
protected readonly Node NodeValue;
internal NodeWrapper()
{
this.NodeValue = new Node();
}
internal NodeWrapper(Node cur_node)
{
this.NodeValue = cur_node;
}
}
class NodeWrapper1 : NodeWrapper
{
internal readonly int ID;
#region ctor
public NodeWrapper1()
{
}
internal NodeWrapper1(Node1 cur_node) : base(cur_node)
{
this.ID = cur_node.ID;
}
#endregion
}
class NodeWrapper2 : NodeWrapper
{
internal readonly int SomeOtherField;
public NodeWrapper2()
{
}
internal NodeWrapper2(Node2 cur_node) : base(cur_node)
{
this.SomeOtherField = cur_node.OtherField;
}
}
#endregion
class IDGenerator
{
private int counter = 0;
private HashSet<int> hs_used_id = new();
internal int GetNewID()
{
while (hs_used_id.Contains(this.counter++)) ;
return this.counter;
}
internal bool AddID(int id) => hs_used_id.Add(id);
}