tags:

views:

991

answers:

10

How do I go about if I need to initialize an object's base with existing object? For example, in this scenario:

public class A
{
    public string field1;
    public string field2;
}

public class B : A
{
    public string field3;
    public void Assign(A source)
    {
        this.base = source; // <-- will not work, what can I do here?
    }
}

Assign() method can, obviously assign values to the base class field-by-field, but isn't there a better solution? Since class B inherits from A, there must be a way to just assign A to the B.base

In C++ this would be a trivial thing to do, but I can't seem to grasp how to do this in .NET

+4  A: 

No the syntax you are trying is not possible in C# .NET you need to do.

public void Assign(A source) {
    field1 = source.field1;
    field2 = source.field2; 
}
Nick Berardi
+10  A: 

Unfortunately base is readonly.

[Edit]
Well perhaps not so unfortunate. The relationship between a base class and a child class is IS-A not HAS-A. By allowing a child class to change the instance of the base class you are allowing the child class to change its own reference since it IS-A base class. If you truly need this functionality then I would suggest you change your inheritance model to reflect what you truly want to do.

Something like this:

public class A
{
    public string field1;
    public string field2;
}

public class B
{
    public string field3;
    public A a;

    public void Assign(A source)
    {
        this.a = source;
    }
}

seems more appropriate and has clearer meaning and functionality.

Andrew Hare
+1 this does smell of inheritance being used for composition.
Dan Blair
I hate to say it, but it looks like this method is the only one I could use :(
galets
This is a way, way roundabouts way of doing it. I'd highly recommend using constructors to set these fields. If a variable is private to a class, it's that way for a reason. If you have a parent class that you want children to manipulate, make the members protected or public.
Robert P
+3  A: 
        public Assign(A a)
        {
            foreach (var prop in typeof(A).GetProperties())
            {
                this.GetType().GetProperty(prop.Name).SetValue(this, prop.GetValue(a, null),null);
            }
        }

Basically, it uses reflection to get all the properties of the base and assign the values of this, to all the values that exist in A.

EDIT: To all you naysayers out there, I quickly tested this now with a base class that had 100 integer variables. I then had this assign method in a subclass. It took 46 milliseconds to run. I don't know about you, but I'm totally fine with that.

BFree
this may technically work, but this is ugly and would slow down the init of the object.
Nick Berardi
I hate when people say reflection is slow. Unless if you're dealing with performance critical code, it's really a non issue. I've done reflection that reflected over many many classes and all of their properties (over an entire DataContext class with 100 tables) and it took no time at all.
BFree
puke! better to advise the individual to not do things like that, or use composition, than to show them how to abuse reflection...
sixlettervariables
I do understand that reflection is not made for that kind of access; I also understand that we were given tools and APIs in order to use them, therefore your solution seems fine. I'm not marking it as an answer, since it's not what I was asking about, but I approve of responsible use of this method
galets
A: 

According to MSDN, "base" can inly be used for the following operations:

  • Call a method on the base class that has been overridden by another method.
  • Specify which base-class constructor should be called when creating instances of the derived class.
Sebastian Dietz
A: 

Why would you need to? By declaring a new B, the CLR automatically calls the constructors for both classes.

B myB = new B();

B new has the fields of both classes. However, you should declare them with an initializer unless you like nulls:

public string field1 = "";
public string field2 = string.Empty;
tsilb
+1  A: 

While there are many excellent answers here, I think the proper way to do this is by chaining the constructors:

public class A
{
    public string field1;
    public string field2;

    public A(string field1, string2 field2)
    {
         this.field1 = field1;
         this.field2 = field2;
    }
}

public class B : A
{
    public string field3;

    public B(string field1, string2 field2, string field3)
        : base(field1, field2)
    {
        this.field3 = field3;
    }
}
DrJokepu
A: 

I hope I'm not the only one who thinks swapping out your base class is a bad design pattern. Another approach is to replace inheritance with composition:

public class A
{
    public string Field1 { get; set; }
    public string Field2 { get; set; }
}

public class B
{
    public A A { get; set; }
    public string Field3 { get; set; }

    public B(A a) { this.A = a; }
}

Now its trivial to write something like this:

B b = new B ( new A { Field1 = "hello", Field2 = "world" } );

b.A = new A { Field1 = "hola", Field2 = "luna" };
Juliet
I don't think OO is a bad design pattern, and you example makes OO totally useless.
Nick Berardi
@Nick: there are plenty of occasions when composition solves problems that inheritance can't. The classic textbook example is when you need to hotswap implementation in one class with another, which is exactly what the author wants to do. (continued...)
Juliet
(from previous) Since the base class is a reference to the object instance, and not just a fancy container, its not possible to swap one base for another. Therefore, the only reasonable solution to the authors problem is to wrap the "base" in a property. Why do you think my approach is wrong?
Juliet
A: 

Wrong question. You're obviously abusing inheritance here. Try to refactor it, so that you keep a reference to A as a member field. If you need polymorphism, consider having common base class or better yet - an interface.

Krzysztof Koźmic
A: 

Is the intent that these fields will be initialized once during object construction, or could "Assign" be called multiple times during an object's lifetime? If the latter, you can disregard the rest of this :)

Andrew's distinction between IS-A and HAS-A is an important one; if the relationship really is a HAS-A, his composition solution is the way to go.

If an IS-A relationship makes more sense (and you are able to modify A), a copy constructor might be a good idea:

public class A
{
    public string field1;
    public string field2;

    public A(A copyFrom)
    {
        this.field1 = copyFrom.field1;
        this.field2 = copyFrom.field2;
    }
}

public class B : A
{
    public string field3;

    public B(A source)
        : base(source)
    {
    }
}

You end up having to copy each of A's properties, but the responsibility for doing so resides in A where it belongs.

John Price
A: 

this.field1 = source.field1; //What is wrong with this?

crazymonkeycoder