Solved

creating copy constructor for c# child class, need help

Posted on 2014-04-15
5
1,257 Views
Last Modified: 2014-04-15
Hello,

I’m a bit stuck on how to create a copy constructor (correct term?) for my child class, using a parent class from a library, as the source.  The goal is to effectively, “convert” the parent class into the child class, so that my existing code can continue to use variables of this class as the parent class, and new code (with a cast) can use the variable as the Child class.

The Parent class from the library is derived from System.Object, and implements the MemberwiseClone function.  I suspect I want to use this protected function in the copy constructor, but I can’t figure out how.

Unfortunately, I’m not even sure how the parent class is initiated:  I think it is done in some other library class, I can’t even see the call to the parent class’s constructor.

So, the question is: Can this be done without knowing details about the Parent class? And if so, what goes in the child’s copy constructor?

Also, considering the sample usage in the code below, should I be making a Deep Copy, rather than a Shallow Copy? (Not really clear on how to implement a Deep copy either.)

    public class Parent : Object
    {
        //implements: protected Object MemberwiseClone()
        //other-wise: black box from a library
        public void Foo() { };
    }

    public class SomeData
    {
        int i=1;
        string str="a";
        string compute() { return str + i.ToString(); }
    }

    public class Child : Parent
    {
        public SomeData additional_data;

        //define copy constructor
        public Child(Parent source,SomeData _additional_data)
        {
            additional_data = _additional_data;
            //... ??  ...
        }
    }

    public class SampleUsage
    {
        public SampleUsage()
        {
            Parent item = new Parent();
            //...
            //item now initialized by black box
            //...
            SomeData data=new SomeData();
            item=new Child(item,data);  //call copy constructor, overwrite original Parent item with newly created child item
            
            //...later on...
            SomeData data_retrieved;
            data_retrieved= ((Child)item).additional_data;
            
            item.Foo();//I've got many line of codes like this one already in existance- dont want to alter them if possible
        }
    }

Open in new window

0
Comment
Question by:Korbus
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 2
5 Comments
 
LVL 23

Accepted Solution

by:
Jens Fiederer earned 500 total points
ID: 40002323
Copy constructor is a correct term if your only parameter is a member of your class.  It is especially significant in C++, where it is actually provided if not present, and called on your behalf in certain instances.

Your

public Child(Parent source,SomeData _additional_data)
        {
            additional_data = _additional_data;
            //... ??  ...
        }

Open in new window


Using  MemberwiseClone isn't really feasible here because it returns a NEW object rather than initializing elements of an existing one.   Also it returns an object of the same type as its parameter rather than a subclass.

You CAN use reflection for that effect, such as:

        public static void CopyProperties(this object destination, object source)
        {
            PropertyInfo[] destinationInfos = destination.GetType().GetProperties();
            Dictionary<string, PropertyInfo> lookup = new Dictionary<string, PropertyInfo>();
            foreach (PropertyInfo destinationInfo in destinationInfos)
            {
                lookup[destinationInfo.Name] = destinationInfo;
            }
            foreach (PropertyInfo sourceInfo in source.GetType().GetProperties())
            {
                PropertyInfo destinationInfo = null;
                if (lookup.TryGetValue(sourceInfo.Name, out destinationInfo))
                {
                    if (sourceInfo.CanRead && destinationInfo.CanWrite)
                    {
                        destinationInfo.SetValue(destination, sourceInfo.GetValue(source, null), null);
                    }
                }
            }
        }

Open in new window


Deep copies require a bit more work in terms of specific code written or a recursion.  Whether deep copy is more or less appropriate depends on more context than your sample provides...nothing there indicates a deep copy is necessary.
0
 
LVL 10

Author Comment

by:Korbus
ID: 40002836
Thank you Jens,

Looks like an unexpected, but very usable solution.
I tried to test it, and found I had left something out of my OP.

The Parent class does NOT have a default constructor.  (Rather it has a constructor that uses two OTHER classes as parameter types that I'm not familiar with.)

So it appears, I don't even have a way to create a new child class.  :(
The compiler is generating this error:
Error      1      'Parent' does not contain a constructor that takes 0 arguments

Am I out of luck, or missing something?
0
 
LVL 23

Expert Comment

by:Jens Fiederer
ID: 40002893
Is this perhaps a Generic Type rather than a real class?  What does it look like?
0
 
LVL 23

Expert Comment

by:Jens Fiederer
ID: 40002895
At any rate, you want to change

Parent item = new Parent();

Open in new window


to the appropriate call.
0
 
LVL 10

Author Closing Comment

by:Korbus
ID: 40002967
The parent class is actually Microsoft.Xna.Framework.Content.ContentManager.  
(An instance of ContentManager is passed to various other classes during initialization for their OnLoad functions.  The goal is to include additional data in this instance, so we can customize some OnLoad functions to use this data, without modifying any class structures.  The catch is, some OTHER class is actually instantiating the instance of ContentManager.)

Alas, I don't know about the parameters this class's constructor takes (IServiceProvider).  I think I was hoping to avoid having to deal with that stuff because I already had an instance of the Parent I wanted to work with.

Guess I'll just need to figure out how to call that constructor.
0

Featured Post

Space-Age Communications Transitions to DevOps

ViaSat, a global provider of satellite and wireless communications, securely connects businesses, governments, and organizations to the Internet. Learn how ViaSat’s Network Solutions Engineer, drove the transition from a traditional network support to a DevOps-centric model.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction Many of the most common information processing tasks require sorting data sets.  For example, you may want to find the largest or smallest value in a collection.  Or you may want to order the data set in numeric or alphabetical order. …
Performance in games development is paramount: every microsecond counts to be able to do everything in less than 33ms (aiming at 16ms). C# foreach statement is one of the worst performance killers, and here I explain why.

740 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question