Неожиданное поведение ссылок в графе узлов
Я пытаюсь создать алгоритм, который включает в себя создание графа узлов (и я не говорю о том, что алгоритм еще не завершен и не работает). Я получаю ввод из файла, а затем создаю новый узел в графе или настраиваю уже существующий, создавая новое соединение между узлами. Мой план состоял в том, что я мог добраться из любого узла в любой другой независимо от расстояния. Когда я редактирую поле "лампы", что-то идет не так, и один соседний узел видит, что еще есть какие-то лампы, что не соответствует действительности, потому что я только что сделал "connection.lamps -= removeLamps". В отладке я вижу, что это поле отличается в двух ссылках, но когда я пытаюсь сделать ReferenceEquals (закомментированный код), он просто везде печатает True. Я думал, что если я отредактирую ссылку, она будет применяться везде. Любая идея, почему это происходит?
internal class Graph
{
public List<Node> nodes = new List<Node>();
}
internal class Node
{
public int number;
public List<Connection> connections = new();
}
internal class Connection
{
public Node nextNode;
public int lamps;
}
internal class Lamps
{
private Graph _graph;
public void GetInput(StreamReader sr)
{
Graph graph = new Graph();
int places_count = int.Parse(sr.ReadLine()); // places
for (int placeIndex = 0; placeIndex < places_count - 1; placeIndex++)
{
var spl = sr.ReadLine().Split(' ');
int input_from = int.Parse(spl[0]), // there is from A
input_to = int.Parse(spl[1]), // to B
input_lamps = int.Parse(spl[2]); // C lamps
Node fromNode, toNode;
if (graph.nodes.Any(x => x.number == input_from))
{
fromNode = FindInGraphByNumber(graph, input_from);
}
else
{
fromNode = new Node();
fromNode.number = input_from;
graph.nodes.Add(fromNode);
}
if (graph.nodes.Any(x => x.number == input_to))
{
toNode = FindInGraphByNumber(graph, input_to);
}
else
{
toNode = new Node();
toNode.number = input_to;
graph.nodes.Add(toNode);
}
fromNode.connections.Add(new Connection() { nextNode = toNode, lamps = input_lamps });
toNode.connections.Add(new Connection() { nextNode = fromNode, lamps = input_lamps });
}
//Console.WriteLine(Node.ReferenceEquals(graph.nodes.First(x => x.number == 3), graph.nodes.First(x => x.number == 1).connections.First(x => x.lamps == 3).nextNode));
//Console.WriteLine(Node.ReferenceEquals(graph.nodes.First(x => x.number == 1), graph.nodes.First(x => x.number == 0).connections.First(x => x.lamps == 1).nextNode));
//Console.WriteLine(Node.ReferenceEquals(graph.nodes.First(x => x.number == 0), graph.nodes.First(x => x.number == 2).connections.First(x => x.lamps == 2).nextNode));
//Console.WriteLine(Node.ReferenceEquals(graph.nodes.First(x => x.number == 2), graph.nodes.First(x => x.number == 5).connections.First(x => x.lamps == 1).nextNode));
//Console.WriteLine(Node.ReferenceEquals(graph.nodes.First(x => x.number == 2), graph.nodes.First(x => x.number == 4).connections.First(x => x.lamps == 1).nextNode));
//Console.WriteLine(Node.ReferenceEquals(graph.nodes.First(x => x.number == 3), graph.nodes.First(x => x.number == 5).connections[0].nextNode.connections.First(x => x.lamps == 2).nextNode.connections.First(x => x.lamps == 1).nextNode.connections.First(x => x.lamps == 3).nextNode));
_graph = graph;
}
private static Node FindInGraphByNumber(Graph graph, int number)
{
for (int graphNodeIndex = 0; graphNodeIndex < graph.nodes.Count; graphNodeIndex++)
{
if (graph.nodes[graphNodeIndex].number == number)
{
return graph.nodes[graphNodeIndex];
}
}
throw new ArgumentException($"{nameof (number)} {number} does not exist in {nameof (graph)}.");
}
public int Proceed()
{
int counter = 0;
while (_graph.nodes.Any(x => x.connections.Any(y => y.lamps > 0)))
{
for (int nodeIndex = 0; nodeIndex < _graph.nodes.Count; nodeIndex++)
{
var node = _graph.nodes[nodeIndex];
// if there is no path with lamps above 0
if (!node.connections.Any(x => x.lamps > 0))
continue;
if (IsEdge(node.number))
{
if (node.connections.Count(x => x.lamps > 0) != 1)
throw new UnreachableException("IsEdge should handle this.");
var edgeNode = node.connections.First(x => x.lamps > 0);
int removeLamps = edgeNode.lamps;
counter += removeLamps;
edgeNode.lamps = 0;
for (int connectedNodeIndex = 0; connectedNodeIndex < edgeNode.nextNode.connections.Count; connectedNodeIndex++)
{
// path from neighboring node
var connection = edgeNode.nextNode.connections[connectedNodeIndex];
// if lamps are not zero or less
if (connection.lamps <= 0)
continue;
connection.lamps -= removeLamps;
}
}
}
}
return counter;
}
private bool IsEdge(int number)
{
var connections = _graph.nodes.First(x => x.number == number).connections;
return connections.Count(x => x.lamps > 0) == 1;
}
}