This code aims to create a hospital data management application using doubly linked circular lists. It can be divided into two main parts:
Classes: The Patient, Medicine, Doctor, and Disease classes represent fundamental data structures for patients, medicines, doctors, and diseases, respectively. Each class includes properties such as ID, name, specialty, etc., and node references (Previous and Next) to represent the doubly linked structure.
Doubly Linked Circular List Class: The Node<T> class represents the nodes of the doubly linked circular list. The DoublyLinkedCircularList<T> class manages the doubly linked circular list based on the data type. The Add method adds a new node to the beginning of the list. The QueryById method searches within the list based on a given ID and returns the corresponding data if found.
Main Program: In the Main method, doubly linked circular lists specific to the Patient, Medicine, Doctor, and Disease types are created. Sample data is added to these lists. The user is prompted to enter an ID, and the program queries patient information using this ID. If found, it displays the information; otherwise, it shows the "Patient not found." message.
Everything is OK, The code is working.But why doesn't the code provide the output of patient information for me? How can I print the patient's doctor, medication and disease information in the code below?
using System;
using System.Collections.Generic;
// Patient class
public class Patient
{
public long? ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Patient? Previous { get; set; }
public Patient? Next { get; set; }
public override string ToString()
{
return $"{ID}. {FirstName} {LastName}";
}
}
// Medicine class
public class Medicine
{
public long? ID { get; set; }
public string Name { get; set; }
public Medicine? Previous { get; set; }
public Medicine? Next { get; set; }
public override string ToString()
{
return $"{ID}. {Name}";
}
}
// Doctor class
public class Doctor
{
public long ID { get; set; }
public string Name { get; set; }
public string Specialty { get; set; }
public Doctor? Previous { get; set; }
public Doctor? Next { get; set; }
public override string ToString()
{
return $"{ID}. {Name} ({Specialty})";
}
}
// Disease class
public class Disease
{
public long ID { get; set; }
public string Name { get; set; }
public Disease? Previous { get; set; }
public Disease? Next { get; set; }
public override string ToString()
{
return $"{ID}. {Name}";
}
}
// Doubly linked circular list class
public class Node\<T\>
{
public T? ID { get; set; }
public Node\<T\>? Previous { get; set; }
public Node\<T\>? Next { get; set; }
}
public class DoublyLinkedCircularList\<T\>
{
private Node\<T\>? Head;
public void Add(T element)
{
Node<T> newNode = new Node<T> { ID = element };
if (Head == null)
{
Head = newNode;
Head.Previous = Head;
Head.Next = Head;
}
else
{
newNode.Previous = Head.Previous;
newNode.Next = Head;
Head.Previous!.Next = newNode;
Head.Previous = newNode;
}
}
public T? QueryById(Func<T, bool> query)
{
if (Head == null)
return default;
Node<T> current = Head;
do
{
if (query(current.ID!))
return current.ID;
current = current.Next!;
} while (current != Head);
return default;
}
}
class Program
{
static void Main(string\[\] args)
{
// Doubly linked circular lists
DoublyLinkedCircularList\<Patient\> patientList = new DoublyLinkedCircularList\<Patient\>();
DoublyLinkedCircularList\<Medicine\> medicineList = new DoublyLinkedCircularList\<Medicine\>();
DoublyLinkedCircularList\<Doctor\> doctorList = new DoublyLinkedCircularList\<Doctor\>();
DoublyLinkedCircularList\<Disease\> diseaseList = new DoublyLinkedCircularList\<Disease\>();
// Add sample data
patientList.Add(new Patient { ID = 46573806740, FirstName = "Hiranur", LastName = "Sazak" });
patientList.Add(new Patient { ID = 23746982347, FirstName = "Nisa Nur", LastName = "Özdal" });
patientList.Add(new Patient { ID = 89374938243, FirstName = "Nisa Gül", LastName = "Ünal" });
patientList.Add(new Patient { ID = 98723424674, FirstName = "Berfin", LastName = "Geleş" });
medicineList.Add(new Medicine { ID = 46573806740, Name = "Theraflu Forte" });
medicineList.Add(new Medicine { ID = 46573806740, Name = "Ketober %1.6 Gargara" });
// ... (add more medicines)
doctorList.Add(new Doctor { ID = 46573806740, Name = "Dr. Ömer Kaplan", Specialty = "Ear, Nose, Throat" });
doctorList.Add(new Doctor { ID = 23746982347, Name = "Dr. Ali Nazmican Güröz ", Specialty = "Orthopedics" });
// ... (add more doctors)
diseaseList.Add(new Disease { ID = 46573806740, Name = "Cold" });
diseaseList.Add(new Disease { ID = 23746982347, Name = "Meniscus Tear" });
// ... (add more diseases)
Console.WriteLine("\n...ID Query...");
Console.Write("Please enter the ID number: ");
if (long.TryParse(Console.ReadLine(), out long ID))
{
Patient? queriedPatient = patientList.QueryById(patient => patient.ID == ID);
if (queriedPatient != null)
{
Console.WriteLine($"ID: {queriedPatient.ID}, First Name: {queriedPatient.FirstName}, Last Name: {queriedPatient.LastName}");
}
else
{
Console.WriteLine("Patient not found.");
}
}
else
{
Console.WriteLine("Invalid ID number entered.");
}
Console.ReadKey();
}
}
As it is the code does not compile. If you remove the extra backslashes it will work. E.g.
Node<T>?instead ofNode\<T\>?andstring[]instead ofstring\[\].Btw.: Circular lists make no sense for this kind of data. There is nothing circular about patients and doctors.
The implementation can be improved. There should be no need to have
PreviousandNextproperties in the data classes. These should only be in theNode<T>class. The nodes should have aDataproperty instead of aIDproperty:Adding some
requiredmodifiers to the properties removes null warnings. TheIDproperties must not be nullable.Adding the comments like
// Medicine classtoclass Medicineadds no value. Comments should add information missing in the code. E.g. design decisions and other non obvious facts.By using primary constructors and getter-only properties we can simplify the classes:
The patients are now initialized like this:
Since
patientList.Addrequires aPatientargument, C# can infer the typePatientand we can write:Circular lists are rarely useful. Therefore lets implement a non circular linked list. Since we never move backwards through the list, the
Previouslink is not required and the list does not need to be doubly linked.The node class is never exposed publicly. Therefore, we can implement it as nested private class. To enable adding elements to the end of the list we also add a reference to the
_tailnode.Note the
: IEnumerable<T>in the class header. It means that the class must implement theIEnumerable<T>interface which is very useful. It enables us to useforeachto loop through the list and gives us access to a lot ofIEnumerable<T>extension methods that are part of the Language INtegrated Query LINQ.Only one method needs to be implemented:
However, we must return an object which implements the
IEnumerator<T>Interface. We implement it as nested private structLinkedListEnumerator. To do this we replace the 3 dots (...) above with:Now we can initialize the patients list by using a collection initializer:
We can loop through the patients like this:
And we can find a patient like this by using LINQ (you may need to add
using System.Linq;at the top of your code):Note that we did not have to implement
QueryByIdas LINQ implements it with the extension methodFirstOrDefault. LINQ uses ourIEnumerable<T>implementation to iterate the list.Another useful interface that we could implement (not shown here) is the
ICollection<T>Interface. It is implemented by a lot of collections and lets us easily replace one collection by another.