Solved

C# inheritance. base object initialization

Posted on 2009-04-10
24
1,110 Views
Last Modified: 2012-05-06
Hi,

I have the following class, the Base that i cannot change and a Child that needs to initialize it's Base part.

class Base // cannot change this class
{
    public int a1 { get; set; }
    public int a2 {get; set; }
    etc..,
}

class Child : Base
{
    public Child( Base obj )
    {
         //question how can i initialize Child's Base part without explicitly assigning every property
    }
}

Thanks.
0
Comment
Question by:keyd
  • 11
  • 8
  • 4
24 Comments
 
LVL 39

Expert Comment

by:abel
Comment Utility
You can do that like so:



class Child : Base

{

    public Child( Base obj ) : base(obj)

    {

         /// your additional initialization

    }

}

Open in new window

0
 
LVL 39

Expert Comment

by:abel
Comment Utility
Note that you are not obliged to call the constructor with the same signature. If you want to call the default constructor of the Base class, you can do it like this (note lowercase of "base" which is a keyword and not your classname):

class Child : Base

{

    public Child( Base obj ) : base()

    {

         /// your additional initialization

    }

}

Open in new window

0
 
LVL 1

Author Comment

by:keyd
Comment Utility
Sorry i guess i wasn't too clear.
The problem is that i cannot change the base class, and also this is not a matter of Child construction, but initialization of base part. The Child class might as well has:

class Child : Base
{
    public Child() { }

    public InitBase( Base objBase )
    {
       //initialize the base part here
    }
}
0
 
LVL 39

Expert Comment

by:abel
Comment Utility
You can only initialize a base class in a constructor. That's mandated by the language C#. If you want to call the constructor from another spot, you'll have to use the aggregator pattern, which means you'll have to rebuild the whole object.

Sorry to give you bad news, but it is simply not possible to initialize something on another spot when it is supposed to already have been initialized (recall that the base class constructor  (Base) is called automatically before the inheriting class (Child) constructor is called, so there really is no other way here and is defined by the language).
0
 
LVL 39

Expert Comment

by:abel
Comment Utility
In addition, you already define it yourself with the declaration:

public InitBase( Base objBase )

which means "give the public method 'initBase' an object of type Base, going by the name 'objBase'. Whenever you call this method, you can only call it with an object of type Base. And an object can only be an object after it is initialized. So either way, the object objBase has to be initialized for the InitBase to work, prior to calling the method.

Again, this is mandated by the language C# (or VB, or any object oriented language like Java, Python, Ruby, Eiffel).
0
 
LVL 1

Author Comment

by:keyd
Comment Utility
I guess i used initialize word wrong.
I'm talking about setting.
Generally i was asking if it is possible to have something like this

void SetBase( Base obj )
{
    (this as Base) = obj; // just an example
    // so to not write something like
    this.a1 = obj.a1;
    this.a2 = obj.a2;
    etc...
}
0
 
LVL 39

Expert Comment

by:abel
Comment Utility
yes, you can access the settings of the base object by using the base keyword. Do not use a base object as parameter:

void SetBase(  )
{
    this.a1 = base.a1;   // refers to the setting of the parent object Base
    this.a2 = base.a2;   // refers to the setting of the parent object Base
}
0
 
LVL 1

Author Comment

by:keyd
Comment Utility
abel, that's exactly what i'm trying to avoid here :-)
NOT have all the properties assigned one by one. I don't care about base keyword.
0
 
LVL 12

Expert Comment

by:williamcampbell
Comment Utility
You might be able to do this if A is a singleton class or a class factory


    class A : B

    {

        static A _instance;

        public

        A (B obj) 

        {

        }

        static void Init( B obj )

        {

           _instance = new A(obj);

        }

    }
 

    class B 

    {

        public

            int a;
 

        public B() { }

    };

Open in new window

0
 
LVL 39

Expert Comment

by:abel
Comment Utility
> NOT have all the properties assigned one by one. I don't care about base keyword.

well, I understand that, but it is "either/or". You simply cannot call the constructor after an object is instantiated, sorry, that is already done at that stage.

I'm not sure what you are after, but it is possible that another approach might suit you:

  • Using .NET it is possible to set properties dynamically, by using reflection, you can even re-call the ctor that way, but this can give unpredictable effects and you need to know quite a lot of what's going on under the hood to get it right. In the end, you probably end up having even more code then doing it the old way using "base" keyword.
  • Another approach is using an extra Init method on Base. Since you say you cannot alter Base, you'd have to create an extra class in the hierarchy that does this for you. Also a lot of work...
  • In .NET 3.5 a tempting approach is using extension methods, but they won't help because they only act on the object. Another dead-end trail...
  • A "hack" style approach is using reflection to call a private method of your Base class. This only works if your base class does the initialization using a method (doesn't matter if the init method is called from the ctor or not). If you have this private init method (you can see that with the object browser or Reflector) then I can help you calling it using reflection.
  • Two other approaches have also been suggested by William in the post before this one.
Bottom line: calling the ctor after the initialization is not possible. Calling it regardless (using reflection) may give unwanted side effects, but can be done in some cases (note that you break the intent of information hiding, an OO principle... but I'm sure you're aware of that ;-). Using any of the other approaches however should have your preference, I hope, as those stick to the "rules" of OO and C#.

-- Abel --
0
 
LVL 1

Author Comment

by:keyd
Comment Utility
i'm aware of all these methods, but none of them is a solution. i guess the answer to my question is no. thanks
0
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 
LVL 12

Expert Comment

by:williamcampbell
Comment Utility
I think this Question was a good conversation on the problem put forward and should be made available to others
0
 
LVL 39

Expert Comment

by:abel
Comment Utility
> i guess the answer to my question is no

this is correct, I said so in some of my posts. I second the objection of William. As you may be aware, "no" is also an answer, and quite a valuable one even though it may be not the one you hoped for.

About no-answers: http://www.experts-exchange.com/help.jsp?hi=405
About grading: http://www.experts-exchange.com/help.jsp?hi=403

However, re-reading your for-last post, I'm still puzzled with the idea. Since it is (almost) impossible to re-init a class, maybe you want something else, esp. now you say that you know all the alternatives, including reflection, already.

You ask how to do something like:

public SetBase(Base obj) {    this = obj;}

but isn't that equal to this (in the clients code):

Base obj = new Base();   // Base object initializedChild childObj = (Child) obj;   // Child object set to Base properties (same obj)

alternatively, if you want to override some behavior but not all, you can create a copy constructor, which is called like this:

Base obj = new Base();   // Base object initialized Child childObj = new Child(obj);   // new Child object set to Base properties (new obj)
-- Abel --
 
0
 
LVL 1

Author Comment

by:keyd
Comment Utility
abel i was going to close this question awarding you points before objection from william. in know that "no" is an answer too, but i think this site is not about giving fast answers and getting the "points", but about discussions and interesting ideas.
So please lets discuss further.

Base obj = new Base();   // Base object initialized
Child childObj = new Child(obj);   // new Child object set to Base properties (new obj)

I'm interested in second line here, what can be in the copy constructor, other that assigning properties one by one.
0
 
LVL 39

Expert Comment

by:abel
Comment Utility
> So please lets discuss further.

great, I totally agree. Give me a moment to elaborate, after breakfast :)
0
 
LVL 39

Accepted Solution

by:
abel earned 500 total points
Comment Utility
after a long breakfast in the sun... ;)

Here: http://msdn.microsoft.com/en-us/library/ms173116(VS.80).aspx, Microsoft shows an example of how they think a copy constructor should look like. This is the traditional approach and I can't remember having seen languages (not even Eiffel, Sather or Oberon) that deal with that differently. Looser languages like Python, Ruby and Perl-OO have easier ways of doing this.

However, there are other ways to deal with that. I'm sure you have a utility class somewhere, if not, just make the following a static method. You can use it to copy any public fields or properties to the other object. Make sure the Source object is the parent (Base). Maybe this is not the ideal method, but at least it does the job for you.

Note that the copy constructor in the example takes a Base object. That makes it easier in terms of castability. Depending on your situation, you may want to amend it a bit. I assumed .NET 3.5 here (using shortcut properties). Call the code as follows:

    Base myBaseObj =  new Base();
    myBaseObj.prop3 = "this is property 3";

    Child myChildObj = new Child(myBaseObj);
    Debug.WriteLine("prop 3: " + myChildObj.prop3);

In the example below I included a copy constructor "traditional style" for the Base class. If you have it, you can use it, if you don't have it, ignore it. The Clone method is the imported part here.

-- Abel --

PS: I first build the method myself and then changed it slightly to match this method I found online: http://www.codeproject.com/KB/dotnet/clone_object_csharp.aspx. There are other ways of cloning, like this one: http://www.codeproject.com/KB/cs/cloneimpl_class.aspx, but I consider the first to be the easiest to implement.

public static class Util

{

    public static void CloneObject(object Source, object Destination)

    {

        // exceptions

        if (Source == null)

            throw new ArgumentNullException("Source");

        if (Destination == null)

            throw new ArgumentNullException("Destination");
 

        // copy each value over

        foreach (PropertyInfo pi in Source.GetType().GetProperties())

            if (pi.CanRead && pi.CanWrite)

                pi.SetValue(Destination, pi.GetValue(Source, null), null);
 

    }

}
 

public class Base

{

    public string prop1 { get; set; }

    public string prop2 { get; set; }

    public string prop3 { get; set; }

    public Base()

    {

        prop1 = "initialized prop1";

        prop2 = "initialized prop2";

    }

    public Base(Base obj)

    {

        // Microsoft's way of a copy constructor

        this.prop1 = obj.prop1;

        this.prop2 = obj.prop2;

    }

}
 

public class Child : Base

{

    public Child() { }

    public Child(Base obj)

        : base(obj)          // calling base(obj) if the base has a copy ctor

    {

        // simpler then Microsoft's method

        Util.CloneObject(obj, this);

    }

}

Open in new window

0
 
LVL 12

Expert Comment

by:williamcampbell
Comment Utility
Amzing what a few eggs and some bacon can do :)

Good Solution.
0
 
LVL 1

Author Comment

by:keyd
Comment Utility
I must say i'm a little disappointed in c# :-) But i guess this was the only possible way.
0
 
LVL 39

Expert Comment

by:abel
Comment Utility
I'm sorry you are disappointed, but I think I gave you quite a lengthy answer and quite to the point. Don't show the disappointed to C# in your appreciation for me diving into details. Don't get me wrong, I love doing it, but I also love getting credits for it.

If you B-grade, there's must be something that you still miss in my answer and give me a chance to elaborate. If you B-grade because you don't like C#'s way of dealing with this, you should reconsider your grade. Remember that EE is all about a 10-points must system: http://www.experts-exchange.com/help.jsp?hi=403.

One more thing about C#. I sometimes don't like C# either, but this particular feature, about initiating an object only once, is equal among all OO languages I have worked with, including C++, Smalltalk, Eiffel, Ruby, C#, VB.NET, Java. Which is why initializable classes expose a method "Init".

-- Abel --
0
 
LVL 1

Author Comment

by:keyd
Comment Utility
Abel, sorry for sounding like my disappointment affected your grade.
But i really think your answer is not full, this solution will not copy entire data state of object, but only public stuff. For implementing copy functionality this is not enough.

EE's 10-points must system: http://www.experts-exchange.com/help.jsp?hi=403.
says:
"If it requires you to do a little more research, or figure out one more piece of code, then it's worth a B"

Still I'll be glad to change the grade if it is possible.
Thanks for your time.
0
 
LVL 12

Expert Comment

by:williamcampbell
Comment Utility
Glad I could help thanks for the ... oh never mind ;)
0
 
LVL 39

Expert Comment

by:abel
Comment Utility
Thanks for the change. I asked earlier whether you wanted the reflection code, and you said you knew all that. It is very easy to amend the above code to work with private, protected, internal fields / properties / methods. If you still need that, I'd be happy to help you there, but you didn't ask, so I didn't know ;-)

-- Abel --
0
 
LVL 1

Author Comment

by:keyd
Comment Utility
Thanks Abel, eventually i took another road with holding Base object instead of deriving it,
Although inheritance would fit nice there :-)
0

Featured Post

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

Extention Methods in C# 3.0 by Ivo Stoykov C# 3.0 offers extension methods. They allow extending existing classes without changing the class's source code or relying on inheritance. These are static methods invoked as instance method. This…
Introduction Hi all and welcome to my first article on Experts Exchange. A while ago, someone asked me if i could do some tutorials on object oriented programming. I decided to do them on C#. Now you may ask me, why's that? Well, one of the re…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

744 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

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now