Search code examples
c#classpass-by-referencepass-by-value

Copy custom list object to another list object


I searched a lot and I know this question has been asked many times, but don't find proper solution for my issue.

I have a class with following structure

namespace Website.Models
{
    public class DynamicControlModel
    {
    }

    public class QuestionnairModel
    {
        public long QuestionId { get; set; }
        public string Question { get; set; }
        public List<QuestionnairOptionModel> QuestionnairOption { get; set; }
    }

    public class QuestionnairOptionModel
    {
        public long OptionId { get; set; }
        public string OptionString { get; set; }
        public bool OptionControl1 { get; set; }
        public string OptionControl2 { get; set; }
    }
}

and I try to do this :

public ActionResult ProcessRequest(List<QuestionnairModel> model)
{
    List<QuestionnairModel> result = new List<QuestionnairModel>(model);
    result = result.Where(x => x.QuestionnairOption.Any(l => l.OptionControl1 == true)).ToList();
    result.ForEach(x => x.QuestionnairOption.RemoveAll(m => m.OptionControl1 == false));
    return View(@"~\Views\Home\About.cshtml", model);
}

Issue over here is when i remove item from result object it gets removed from model as well. I want model object should not get affected due to any change in result object.

I know class is by default pass by reference and that's why it gets removed from both the object.

Let me know how can i make it Pass by value which might solve the issue.


Solution

  • Thanks to @David Pilkington

    I have resolved my issue using below code.

    
         public static class ObjectCopier
        {
            /// 
            /// Perform a deep Copy of the object.
            /// 
            /// The type of object being copied.
            /// The object instance to copy.
            /// The copied object.
            public static T Clone(T source)
            {
                if (!typeof(T).IsSerializable)
                {
                    throw new ArgumentException("The type must be serializable.", "source");
                }
    
                // Don't serialize a null object, simply return the default for that object
                if (Object.ReferenceEquals(source, null))
                {
                    return default(T);
                }
    
                IFormatter formatter = new BinaryFormatter();
                Stream stream = new MemoryStream();
                using (stream)
                {
                    formatter.Serialize(stream, source);
                    stream.Seek(0, SeekOrigin.Begin);
                    return (T)formatter.Deserialize(stream);
                }
            }
        }
    
    

    The only change i did in my existing code is added [Serializable] attribute to my class like this.

    
         [Serializable]
        public class QuestionnairModel
        {
            public long QuestionId { get; set; }
            public string Question { get; set; }
            public List QuestionnairOption { get; set; }
        }
    
        [Serializable]
        public class QuestionnairOptionModel
        {
            public long OptionId { get; set; }
            public string OptionString { get; set; }
            public bool OptionControl1 { get; set; }
            public string OptionControl2 { get; set; }
        }