Solved

C# inheritance. base object initialization

Posted on 2009-04-10
24
1,120 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
[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
  • 11
  • 8
  • 4
24 Comments
 
LVL 39

Expert Comment

by:abel
ID: 24114888
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
ID: 24114899
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
ID: 24114976
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
[Live Webinar] The Cloud Skills Gap

As Cloud technologies come of age, business leaders grapple with the impact it has on their team's skills and the gap associated with the use of a cloud platform.

Join experts from 451 Research and Concerto Cloud Services on July 27th where we will examine fact and fiction.

 
LVL 39

Expert Comment

by:abel
ID: 24115024
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
ID: 24115049
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
ID: 24115102
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
ID: 24115241
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
ID: 24115718
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
ID: 24117156
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
ID: 24118805
> 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
ID: 24119091
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
 
LVL 12

Expert Comment

by:williamcampbell
ID: 24119274
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
ID: 24121291
> 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
ID: 24121426
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
ID: 24121660
> 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
ID: 24122702
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
ID: 24124046
Amzing what a few eggs and some bacon can do :)

Good Solution.
0
 
LVL 1

Author Comment

by:keyd
ID: 24133097
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
ID: 24133353
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
ID: 24133464
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
ID: 24133844
Glad I could help thanks for the ... oh never mind ;)
0
 
LVL 39

Expert Comment

by:abel
ID: 24135648
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
ID: 24135801
Thanks Abel, eventually i took another road with holding Base object instead of deriving it,
Although inheritance would fit nice there :-)
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

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

Introduction This article series is supposed to shed some light on the use of IDisposable and objects that inherit from it. In essence, a more apt title for this article would be: using (IDisposable) {}. I’m just not sure how many people would ge…
Calculating holidays and working days is a function that is often needed yet it is not one found within the Framework. This article presents one approach to building a working-day calculator for use in .NET.
In this video you will find out how to export Office 365 mailboxes using the built in eDiscovery tool. Bear in mind that although this method might be useful in some cases, using PST files as Office 365 backup is troublesome in a long run (more on t…
Sometimes it takes a new vantage point, apart from our everyday security practices, to truly see our Active Directory (AD) vulnerabilities. We get used to implementing the same techniques and checking the same areas for a breach. This pattern can re…

624 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