This is a follow up question to my previous one, Make a deep copy of an object inside a ConcurrentDictionary in C#. I want to clone my Patient
object so that the object
PatientCovariates
is the same for the copy.
But when I do that, I also want to regenerate the Random Crn
to the same object that was created when the Patient
struct was constructed by using _seed
.
At the same time, I would like to keep Crn
readonly
and _seed
private
and readonly
. Is this possible?
using System.Collections.Concurrent;
using System.Text.Json;
namespace ExampleCode;
internal class Program
{
private static void Main(string[] args)
{
Exampel obj = new();
obj.DoStuff();
}
}
internal class Exampel()
{
/// <summary>
/// For the baseline patients (patient ID, patient object), same for all arms and only generated once
/// </summary>
private ConcurrentDictionary<int,
Patient> _baselinePatients = new();
/// <summary>
/// Patients in the current arm (patient ID, patient object)
/// </summary>
private ConcurrentDictionary<int,
Patient> _patientsCurrentArm = new();
public void DoStuff()
{
const int EXAMPLE_CYCLE = 0;
// Set the number of arms and treatments
int _nArms = 2;
int _nPatients = 5;
// Add patients at baseline to _baselinePatients
for (int i = 0; i < _nPatients; i++) {
Patient patient = new Patient(1);
patient.PatientCovariates.Add(0, new());
_baselinePatients.TryAdd(i, patient);
}
// Try to copy the patients created in the baseline ConcurrentDictionary
for (int i = 0; i < _nArms; i++) {
for (int j = 0; j < _nPatients; j++) {
Patient patObjCopy = (Patient)_baselinePatients[j].Clone();
Patient patObjCopyTwo = (Patient)patObjCopy.Clone();
patObjCopy.PatientCovariates[EXAMPLE_CYCLE].Add("Covariate for patient ", // To mark the arm name and make the patient struct different
j.ToString() +
" in arm " +
i.ToString());
// Save the patient copy in the _patientsCurrentArm WITHOUT changing the patient in _baselinePatients
_patientsCurrentArm.TryAdd(j, patObjCopy);
}
}
}
internal struct Patient : ICloneable
{
private readonly int _seed; // used when the object is copied to regenerated the Crn
public readonly Random Crn { get; }
/// <summary>
/// Cycle, covariate name, covariate value
/// </summary>
public Dictionary<int,
Dictionary<string,
string>> PatientCovariates
{ get; set; }
/// <summary>
/// Initiates PatientCovariates
/// </summary>
public Patient(int seed)
{
_seed = seed;
Crn = new(_seed);
PatientCovariates = new();
}
/// <summary>
/// Clone patients
/// </summary>
/// <returns></returns>
public readonly object Clone()
{
Patient patient = new() {
// Here, I also want to regenerate the Crn by using _seed, as was done when the patient was constructed
PatientCovariates = this.PatientCovariates.ToDictionary(
entry => entry.Key,
entry => entry.Value.ToDictionary(
innerEntry => innerEntry.Key,
innerEntry => innerEntry.Value
)
)
};
return patient;
}
}
}
Thanks to @Charlieface, I found a solution. I can just use the existing constructor and make Random Crn
being readonly
.
public readonly object Clone()
{
Patient patient = new(_seed) {
PatientCovariates = this.PatientCovariates.ToDictionary(
entry => entry.Key,
entry => entry.Value.ToDictionary(
innerEntry => innerEntry.Key,
innerEntry => innerEntry.Value
)
)
};
return patient;
}