0

Assume the code below. Is it possible to create a derived class using an instance of the existing base class? Or is using extension methods the best solution here?

public class TestThis
{
    public void Test1()
    {
        A a = GetAFromExternalSystem();

        B b = new B(a);

        a.Value = 5;

        b.Value == 5; //want this line to return true.  In other words, b to hold a reference to a.
    }

    private A GetAFromExternalSystem()
    {
        return new A();
    }
}

public class A
{
    public string Name { get; set; }
    public int Value { get; set; }
}

public class B : A
{
    public B(A a)
    {
        this = a;  //Cannot assign to 'this' because it is read-only
    }
    public int Ranking { get; set; }
}
Kevin McDowell
  • 532
  • 6
  • 20
  • 1
    Possible duplicate of [Is it possible to assign a base class object to a derived class reference with an explicit typecast in C#?](http://stackoverflow.com/questions/729527/is-it-possible-to-assign-a-base-class-object-to-a-derived-class-reference-with-a) – weir Feb 07 '17 at 20:17
  • _derived class using an instance of the existing base class_ If I understand what you are saying, this is a misconception. A subclass inherits from a parent **class**. Not from the **object**. – chadnt Feb 07 '17 at 20:19

3 Answers3

3

Here's how you would typically do this:

public class A
{
    public A(string name, int value) 
    {
      this.Name = name;
      this.Value = value;
    }
    public string Name { get; set; }
    public int Value { get; set; }
}

public class B : A
{
    public B(A a) : this(a.Name, a.Value, 0)
    {
    }
    public B(string name, int value, int ranking) : base(name, value)
    {
      this.Ranking = ranking;
    }
    public int Ranking { get; set; }
}

Study this carefully and make sure you understand how it works. If you have a question about how it works, post a new, precise, clear question.

Now, this does not have the property that you want, namely, that updates to A also update B. The way to do that odd thing is to abandon the is-a-kind-of relationship between B and A:

public class B
{
    private A a;
    public B(A a)
    {
      this.a = a;
    }
    public int Ranking { get; set; }
    public int Value 
    { 
      get { return this.a.Value; }
      set { this.a.Value = value; }
    }
    public string Name 
    { 
      get { return this.a.Name; } 
      set { this.a.Name = value; }
    }  
}

Now, if you want to have both B deferring to A, and also B being an instance of A, then you have a harder problem; the properties of A have to be virtual, and overridden in B. I leave that as an exercise.

But really it sounds like you are trying to do something very strange here. Can you describe the problem you're actually trying to solve? Odds are pretty good you're doing it wrong.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • Maybe the OP should know that you've shown `Inheritance` and `Composition` patterns ? – aybe Feb 07 '17 at 21:07
  • The specific problem is testing a Microsoft Word taskpane add-in. – Kevin McDowell Feb 10 '17 at 00:46
  • My test class has an accessor property populated by an IHTMLElementCollection of HTMLLIElementClass objects contained within the taskpane. That collection is dynamic. If changes are made in the taskpane, that collection (when accessed from the property) reflects those changes. For example, the collection count is correct and individual HTMLLIElementClass properties, like position properties are correct. – Kevin McDowell Feb 10 '17 at 00:46
  • I wanted to derive from the HTMLLIElementClass and keep that dynamic link. My first attempt was to simply create a helper class that had a reference to individual HTMLLIElementClass objects. But as soon as I set the reference, the dynamic connection was lost. I had hoped that by deriving from the HTMLLIElementClass I could keep that live reference. – Kevin McDowell Feb 10 '17 at 00:46
  • So, you're solution isn't to use inheritance, but to simply wrap the base class with a custom class? While my original example was pretty generic, to actually implement this with my real-world scenario, I'd have to write get/set properties for every property I need off of the HTMLLIElementClass, correct? – Kevin McDowell Feb 10 '17 at 00:46
  • @KevinMcDowell: Coincidentally, I worked on the original version of the task pane add-in infrastructure back in... 2003? Or thereabouts. Haven't touched it since. What you're doing here is called an X/Y problem: you have an actual problem, you've proposed a solution, and now you're asking a question about the solution rather than a problem. (http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) **Post a question about your real problem and try to get an expert on Word task pane add-ins to help you**. I am not such an expert; I haven't looked at that code in over a decade. – Eric Lippert Feb 10 '17 at 02:17
2

No, you cannot do this.

When a derived class is created, the base class is also created and is "part" of the derived class. You cannot simply reassign the base part of the derived class to something else.

The fix is pretty easy though, just copy over the members you care about.

BradleyDotNET
  • 60,462
  • 10
  • 96
  • 117
0

You cannot do this with a derived class, although this may be an X / Y Problem. To achieve what you are trying to achieve in your test case can be done using a wrapper class

public class TestThis
{
    public void Test1()
    {
        A a = GetAFromExternalSystem();

        B b = new B(a);

        a.Value = 5;

        b.Value == 5;
    }

    private A GetAFromExternalSystem()
    {
        return new A();
    }
}

public class A
{
    public string Name { get; set; }
    public int Value { get; set; }
}

public class B  // B acts as a 'wrapper' for A
{
    public B(A a)
    {
        this.A = a;
    }
    public A A { get; set; }
    public int Value { 
        get { return A.Value; }
    }
    public int Ranking { get; set; }
}
Community
  • 1
  • 1
maraaaaaaaa
  • 7,749
  • 2
  • 22
  • 37